/* Copyright(C) 1999, Swedish Institute of Computer Science */

#include "fd.h"
#include "dvars.h"

/*
  '$fd_linear'(+State0, -State, -Actions).
  State = state(CX,Op,RHS,Nground,Handle,Stamp) where CX are all non-ground
  Op in [1,2,3,4] means [#=<,#>=,#=,#\=].
*/
void SPCDECL
prolog_fd_linear MAGIC (HIDDEN_PROTO
			SP_term_ref State0,
			SP_term_ref State,
			SP_term_ref Actions)
{
  WAMENV;
  TAGGED telt;
  int ent;

  (void)State0;                 /* [PM] 3.9b5 avoid -Wunused */

  DerefArg(telt,X(0),2);

  if (GetSmall(telt) & 0x8) {
    ent = fd_linear_filter_fast(w,State);
  } else {
    ent = fd_linear_filter(w,State);
  }
  if (ent==1)
    Pfree;
  dvar_export_done(w,Actions, ent);
}

#if MULTI_SP_AWARE
#define plan_divmodrem(A1,A2) plan_divmodrem(HIDDEN_ARG, A1,A2) 
#define dvar_fix_min_safe(A1,A2) dvar_fix_min_safe(HIDDEN_ARG, A1,A2) 
#define dvar_fix_max_safe(A1,A2) dvar_fix_max_safe(HIDDEN_ARG, A1,A2) 
#define mod_integer(A1,A2) mod_integer(HIDDEN_ARG, A1,A2) 
#define rem_integer(A1,A2) rem_integer(HIDDEN_ARG, A1,A2) 
#endif /* MULTI_SP_AWARE */

/* returns TRUE on overflow */
/* ripped off from wamfunc.c */
static SP_BOOL long_mult(SP_WORD x, SP_WORD y, SP_WORD *productp)
{
  SP_UWORD lower, tmp;
  UHALF x0, x1, y0, y1;
  int negated;
  
  if (x>>HALFSHIFT==x>>(HALFSHIFT-1) &&
      y>>HALFSHIFT==y>>(HALFSHIFT-1)) {
    *productp = x*y;
    return FALSE;
  }

  negated = 0;
  if (x<0)
    x = -x, negated ^= 1;
  if (y<0)
    y = -y, negated ^= 1;

  x0 = LOWER_UHALF(x);
  x1 = (UHALF)(x>>HALFSHIFT);
  y0 = LOWER_UHALF(y);
  y1 = (UHALF)(y>>HALFSHIFT);

  lower = 0L;
  if (x0 && y0) {
    lower = (SP_UWORD)x0*(SP_UWORD)y0;
  }
  if (x1 && y1) {
    return TRUE;
  } else if (x0 && y1) {
    tmp = (SP_UWORD)x0*(SP_UWORD)y1 + (lower>>HALFSHIFT);
    if (tmp>>HALFSHIFT)
      return TRUE;
    else
      lower = (tmp<<HALFSHIFT) + LOWER_UHALF(lower);
  } else if (x1 && y0) {
    tmp = (SP_UWORD)x1*(SP_UWORD)y0 + (lower>>HALFSHIFT);
    if (tmp>>HALFSHIFT)
      return TRUE;
    else
      lower = (tmp<<HALFSHIFT) + LOWER_UHALF(lower);
  }
  if ((SP_WORD)lower<0L && (lower<<1L || !negated))
    return TRUE;
  if (negated)
    lower = -lower;
  *productp = lower;
  return FALSE;
}

/* precond: t1 and t2 are tagged integers */
static TAGGED fd_safe_mul_val(TAGGED t1, TAGGED t2)
{
  long st = GetSmall(t1);
  long su = GetSmall(t2);
  long prod;
  
  if (!long_mult(st,su,&prod) && IntIsSmall(prod))
    return MakeSmall(prod);
  else
    return (((st<0)^(su<0)) ? Inf : Sup);
}

/* operations exported to indexical.c */

TAGGED fd_safe_mul(TAGGED t1, TAGGED t2)
{
  if (TagIsSmall(t1)) {
    if (TagIsSmall(t2))
      t1 = fd_safe_mul_val(t1,t2);
    else if (Teqz(t1))
      return ERRORTAG;	/* 0*inf -> give up */
    else
      t1 = (Tltz(t1)^(t2==Inf) ? Inf : Sup);
  } else if (TagIsSmall(t2)) {
    if (Teqz(t2))
      t1 = ERRORTAG;		/* inf*0 -> give up */
    else
      t1 = (Tltz(t2)^(t1==Inf) ? Inf : Sup);
  } else
    t1 = (t1!=t2 ? Inf : Sup);
  return t1;
}

/* ceiling of quotient, SmallxSmall */
static TAGGED fd_safe_divu_val(TAGGED t1, TAGGED t2)
{
  if (Tnez(t2)) {
    SP_WORD x = GetSmall(t1);
    SP_WORD y = GetSmall(t2);
    SP_WORD q = (  x==0 ? 0
		: (x<0)^(y<0) ? x/y 
		: x>0 ? (x+y-1)/y
		: (x+y+1)/y
		);
    t1 = MakeSmall(q);
  } else if (Tltz(t1))
    t1 = Inf;
  else if (Tgtz(t1))
    t1 = Sup;
  else
    t1 = ERRORTAG;	/* 0/0 -> give up */
  return t1;
}


/* ceiling of quotient */
TAGGED fd_safe_divu(TAGGED t1, TAGGED t2)
{
  if (TagIsSmall(t1)) {
    if (TagIsSmall(t2))
      t1 = fd_safe_divu_val(t1,t2);
    else if (Tnez(t1))	/* +/sup, -/inf -> 1 */
      t1 = (Tltz(t1)^(t2==Inf) ? TaggedZero : TaggedOne);
  } else if (TagIsSmall(t2))
    t1 = (Tltz(t2)^(t1==Inf) ? Inf : Sup);
  else
    t1 = ERRORTAG;		/* inf/inf -> give up */
  return t1;
}

/* floor of quotient, SmallxSmall */
static TAGGED fd_safe_divd_val(TAGGED t1, TAGGED t2)
{
  if (Tnez(t2)) {
    SP_WORD x = GetSmall(t1);
    SP_WORD y = GetSmall(t2);
    SP_WORD q = ( x==0 ? 0
	       : (x<0)^(y>0) ? x/y 
	       : x>0 ? (x-y-1)/y
	       : (x-y+1)/y
	       );
	      
    t1 = MakeSmall(q);
  } else if (Tltz(t1))
    t1 = Inf;
  else if (Tgtz(t1))
    t1 = Sup;
  else
    t1 = ERRORTAG;	/* 0/0 -> give up */
  return t1;
}

/* floor of quotient */
TAGGED fd_safe_divd(TAGGED t1, TAGGED t2)
{
  if (TagIsSmall(t1)) {
    if (TagIsSmall(t2)) {
      t1 = fd_safe_divd_val(t1,t2);
    } else if (Tnez(t1))	/* -/sup, +/inf -> -1 */
      t1 = (Tltz(t1)^(t2==Sup) ? TaggedZero : TaggedMinusOne);
  } else if (TagIsSmall(t2))
    t1 = (Tltz(t2)^(t1==Inf) ? Inf : Sup);
  else
    t1 = ERRORTAG;		/* inf/inf -> give up */
  return t1;
}

TAGGED fd_safe_plus(TAGGED t1, TAGGED t2)
{
  if (TagIsSmall(t1)) {
    if (TagIsSmall(t2)) {
      TADDCHK(t1,t2);
    } else
      t1 = t2;
  }
  return t1;
}

TAGGED fd_safe_minus(TAGGED t1, TAGGED t2)
{
  if (TagIsSmall(t1)) {
    if (TagIsSmall(t2)) {
      TSUBCHK(t1,t2);
    } else
      t1 = (t2==Inf ? Sup : Inf);
  }
  return t1;
}

static TAGGED fd_safe_negate_val(TAGGED t1)
{
  TAGGED t2 = Tminus(t1);
  return (t2==TaggedZero ? t2 : t2!=t1 ? t2 : Sup);
}

static TAGGED fd_safe_negate(TAGGED t1)
{
  return (TagIsSmall(t1) ? fd_safe_negate_val(t1) : t1==Inf ? Sup : Inf);
}

static TAGGED fd_safe_min(TAGGED t1,TAGGED t2)
{
  return (FDlt(t1,t2) ? t1 : t2);
}

static TAGGED fd_safe_max(TAGGED t1,TAGGED t2)
{
  return (FDgt(t1,t2) ? t1 : t2);
}

static long fast_modi(long i1, long i2)
{
  long value = i1 % i2;
  if (value != 0 && (value < 0) != (i2 < 0))
    value += i2;
  return value;
}

struct arith_data {
  void (SPCDECL *destructor)(void *);
#if MULTI_SP_AWARE
  SPEnv *spenv;
#endif /* MULTI_SP_AWARE */
  SP_globref refbase;
  Dvar dvar;
  int nrefs;
};

#define xmin dvar_min_t(dvx)
#define xmax dvar_max_t(dvx)
#define ymin dvar_min_t(dvy)
#define ymax dvar_max_t(dvy)
#define zmin dvar_min_t(dvz)
#define zmax dvar_max_t(dvz)

static void SPCDECL arith_destructor(void *pdata_v)
{
  struct arith_data *pdata = (struct arith_data*)pdata_v;
  FD_SETUP_SPENV(pdata->spenv)

  SP_free_globrefs(pdata->refbase,pdata->nrefs);
  SP_free(pdata);
}

#define CEILSQRT \
  { \
    long m = GetSmall(ymin); \
    if (m>=3) \
      {			/* m = ceiling(sqrt(m)) */ \
	long n1 = m>>1, n2 = m; \
	while (n1<m) \
	  m = n1, \
	  n1 = (n1 + n2/n1)>>1; \
	if (m<n1 || m*m < n2) \
	  m++; \
      } \
    sqrt_ymin = MakeSmall(m); \
    ymin_align = MakeSmall(m*m); \
  }

#define FLOORSQRT \
    { \
      long n = GetSmall(ymax); \
      if (n>=2) \
	{			/* n = floor(sqrt(n)) */ \
	  long n1 = n>>1, n2 = n; \
 \
	  while (n1<n) \
	    n = n1, \
	    n1 = (n1 + n2/n1)>>1; \
	} \
      sqrt_ymax = MakeSmall(n); \
    }

/*
  '$fd_square'(State0, State, -Actions).
  State = state(X, XMut, Y, YMut)
*/
void SPCDECL
prolog_fd_square MAGIC (HIDDEN_PROTO
			SP_term_ref State,
			SP_term_ref NewState,
			SP_term_ref Actions)
{
  WAMENV;
  Dvar dvx, dvy;
  TAGGED newmin=0, newmax=0;
  TAGGED sqrt_ymin, sqrt_ymax, ymin_align;
  TAGGED handle;
  SP_BOOL committed;
  struct arith_data *pdata;
  int ent = -1;			/* disentailed unless otherwise */

  (void)State;                 /* [PM] 3.9b5 avoid -Wunused */
/*    X(0) = RefTerm(State0); */
  w->numstack_end = NULL;
  dvar_export_start(w);
  RefTerm(NewState) = fd_static_output_state(w,&handle,&committed);
  if (!IsVar(handle)) {		/* got [Flag | '$free'(Ptr)] */
    pdata = Pdata(struct arith_data,handle);
  } else {			/* build persistent state */
    pdata = Palloc(struct arith_data, 2*sizeof(struct dvar), handle);
    pdata->destructor = arith_destructor;
    pdata->nrefs = 4;
    FD_STORE_SPENV(pdata->spenv);
    pdata->refbase = SP_alloc_globrefs(4);
    pdata->dvar = (Dvar)(pdata+1);
    fd_get_var_and_attr(X(0),pdata->refbase);
    fd_get_var_and_attr(X(0)+WD(2),pdata->refbase+2);
  }

  /* RESUME HERE */
  dvx = pdata->dvar;
  dvy = dvx+1;
  dvar_init(dvx, pdata->refbase,   pdata->refbase+1);
  dvar_init(dvy, pdata->refbase+2, pdata->refbase+3);
  sqrt_ymin = ymin;
  sqrt_ymax = ymax;
    
  CEILSQRT;
  if (TagIsSmall(ymax))
    FLOORSQRT;

  switch ((!TagIsSmall(xmin) ? 0x0 : Tltz(xmin) ? 0x4 : 0x8)+
	  (!TagIsSmall(xmax) ? 0x0 : Tltz(xmax) ? 0x1 : 0x2)) {
  case 0x0:		/* inf..sup */
  case 0x2:		/* inf..+b */
  case 0x4:		/*  -a..sup */
    newmin = ymin;
    newmax = ymax;
    break;
  case 0x1:		/* inf..-b => b^2..sup */
    newmin = fd_safe_mul_val(xmax,xmax);
    newmax = ymax;
    break;
  case 0x5:		/*  -a..-b => b^2..a^2 */
    newmin = fd_safe_mul_val(xmax,xmax);
    newmax = fd_safe_mul_val(xmin,xmin);
    break;
  case 0x6:		/*  -a..b => 0..max(a^2,b^2) */
    if (Tlt(xmin,Tminus(xmax)))
      newmax = fd_safe_mul_val(xmin,xmin);
    else
      newmax = fd_safe_mul_val(xmax,xmax);
    break;
  case 0x8:		/* a..sup => a^2..sup */
    newmin = fd_safe_mul_val(xmin,xmin);
    newmax = ymax;
    break;
  case 0xa:		/*  a..b => a^2..b^2 */
    newmin = fd_safe_mul_val(xmin,xmin);
    newmax = fd_safe_mul_val(xmax,xmax);
    break;
  }
  if (FDgt(ymin_align,newmin))
    newmin = ymin_align;
  if (dvar_fix_interval_t(dvy, newmin, newmax)<0)
    goto fail_or_oflo;

  newmin = fd_safe_negate(sqrt_ymax);
  newmax = fd_safe_negate(sqrt_ymin);
  if (dvar_compare_interval_t(dvx, newmin, newmax,w)==FDI_DISJOINT) {
    newmin = sqrt_ymin;
    newmax = sqrt_ymax;
  } else if (dvar_compare_interval_t(dvx, sqrt_ymin, sqrt_ymax,w)!=FDI_DISJOINT) {
    newmax = sqrt_ymax;
  }
  if (dvar_fix_interval_t(dvx, newmin, newmax)<0)
    goto fail_or_oflo;
  
  ent = dvar_is_integer_first(dvx);
  
  dvar_export(w,dvx);
  dvar_export(w,dvy);
  goto ret;
  
fail_or_oflo:
  if (newmin==Sup || newmax==Inf) /* can't represent bounds */
    fd.fd_overflow = TRUE;
 ret:
  if (ent==1)
    Pfree;
  dvar_export_done(w,Actions, ent);
}


static SP_BOOL 
is_supported_divider(long d,
		     TAGGED prod_min,
		     TAGGED prod_max,
		     TAGGED fact_min,
		     TAGGED fact_max)
{
  long pmin = GetSmall(prod_min);
  long pmax = GetSmall(prod_max);
  int sign = 0;

  if (pmin<0) {
    sign++;
    pmax = -GetSmall(prod_min);
    pmin = -GetSmall(prod_max);
  }
  if (d<0) {
    sign++;
    d = -d;
  }
  if ((pmin-1)/d==pmax/d)
    return FALSE;
  pmin = (pmin-1)/d+1;
  pmax /= d;
  if (sign!=1) {
    prod_min = MakeSmall(pmin);
    prod_max = MakeSmall(pmax);
  } else {
    prod_max = MakeSmall(-pmin);
    prod_min = MakeSmall(-pmax);
  }
  if (fd_compare_intervals(prod_min,prod_max,fact_min,fact_max)==FDI_DISJOINT)
    return FALSE;
  return TRUE;
}

#define ARITH_DISPATCH(xmin,xmax,ymin,ymax)			\
         ((!TagIsSmall(xmin) ? 0x00 :				\
	   Tltz(xmin) ? 0x40 : Teqz(xmin) ? 0x80 : 0xc0)+	\
	  (!TagIsSmall(xmax) ? 0x30 :				\
	   Tltz(xmax) ? 0x00 : Teqz(xmax) ? 0x10 : 0x20)+	\
	  (!TagIsSmall(ymin) ? 0x00 :				\
	   Tltz(ymin) ? 0x04 : Teqz(ymin) ? 0x08 : 0x0c)+	\
	  (!TagIsSmall(ymax) ? 0x03 :				\
	   Tltz(ymax) ? 0x00 : Teqz(ymax) ? 0x01 : 0x02))	\

/* -1=overflow, 0=fail, 2=no pruning, 1=pruning */
static int fd_product_inverse_dispatch(Dvar dvx,
				       Dvar dvy,
				       Dvar dvz)
{
  TAGGED newmin, newmax;
  int x_is_mon=0;
  
  switch (ARITH_DISPATCH(xmin,xmax,ymin,ymax)) {
				/* automatically generated table! */
  case 0x90: /* 0-0 / inf- -(d) => 0-0 */
  case 0x94: /* 0-0 / -(c)- -(d) => 0-0 */
  case 0x9e: /* 0-0 / +(c)- +(d) => 0-0 */
  case 0x9f: /* 0-0 / +(c)-sup => 0-0 */
    newmin = TaggedZero;
    newmax = TaggedZero;
    break;
  case 0xeb: /* +(a)- +(b) / 0-sup => 1-b */
    x_is_mon = 1;
    newmin = TaggedOne;
    newmax = xmax;
    break;
  case 0x0: /* inf- -(b) / inf- -(d) => 1-sup */
  case 0x1: /* inf- -(b) / inf-0 => 1-sup */
  case 0xfb: /* +(a)-sup / 0-sup => 1-sup */
  case 0xff: /* +(a)-sup / +(c)-sup => 1-sup */
    newmin = TaggedOne;
    newmax = zmax;
    break;
  case 0x10: /* inf-0 / inf- -(d) => 0-sup */
  case 0x14: /* inf-0 / -(c)- -(d) => 0-sup */
  case 0xbe: /* 0-sup / +(c)- +(d) => 0-sup */
  case 0xbf: /* 0-sup / +(c)-sup => 0-sup */
    newmin = TaggedZero;
    newmax = zmax;
    break;
  case 0x41: /* -(a)- -(b) / inf-0 => 1- -(a) */
    x_is_mon = 1;
    newmin = TaggedOne;
    newmax = fd_safe_negate_val(xmin);
    break;
  case 0x40: /* -(a)- -(b) / inf- -(d) => 1-a/d */
    x_is_mon = 1;
    newmin = TaggedOne;
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymax)));
    break;
  case 0x50: /* -(a)-0 / inf- -(d) => 0-a/d */
  case 0x54: /* -(a)-0 / -(c)- -(d) => 0-a/d */
    newmin = TaggedZero;
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymax)));
    break;
  case 0xae: /* 0- +(b) / +(c)- +(d) => 0-b/c */
  case 0xaf: /* 0- +(b) / +(c)-sup => 0-b/c */
    newmin = TaggedZero;
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymin)));
    break;
  case 0xef: /* +(a)- +(b) / +(c)-sup => 1-b/c */
    x_is_mon = 1;
    newmin = TaggedOne;
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymin)));
    break;
  case 0x9: /* inf- -(b) / 0-0 => 1-0 */
  case 0x49: /* -(a)- -(b) / 0-0 => 1-0 */
  case 0xe9: /* +(a)- +(b) / 0-0 => 1-0 */
  case 0xf9: /* +(a)-sup / 0-0 => 1-0 */
    return 0;
  case 0x4b: /* -(a)- -(b) / 0-sup => a- -1 */
    x_is_mon = 1;
    newmin = xmin;
    newmax = TaggedMinusOne;
    break;
  case 0x42: /* -(a)- -(b) / inf- +(d) => a- -(a) */
  case 0x43: /* -(a)- -(b) / inf-sup => a- -(a) */
  case 0x46: /* -(a)- -(b) / -(c)- +(d) => a- -(a) */
  case 0x47: /* -(a)- -(b) / -(c)-sup => a- -(a) */
    x_is_mon = 1;
    newmin = xmin;
    newmax = fd_safe_negate_val(xmin);
    break;
  case 0x4a: /* -(a)- -(b) / 0- +(d) => a-b/d */
    x_is_mon = 1;
    newmin = xmin;
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymax)));
    break;
  case 0xf: /* inf- -(b) / +(c)-sup => inf- -1 */
  case 0xf0: /* +(a)-sup / inf- -(d) => inf- -1 */
    newmin = zmin;
    newmax = TaggedMinusOne;
    break;
  case 0xb: /* inf- -(b) / 0-sup => inf- -1 */
  case 0xf1: /* +(a)-sup / inf-0 => inf- -1 */
    newmin = zmin;
    newmax = TaggedMinusOne;
    break;
  case 0x1e: /* inf-0 / +(c)- +(d) => inf-0 */
  case 0x1f: /* inf-0 / +(c)-sup => inf-0 */
  case 0xb0: /* 0-sup / inf- -(d) => inf-0 */
  case 0xb4: /* 0-sup / -(c)- -(d) => inf-0 */
    newmin = zmin;
    newmax = TaggedZero;
    break;
  case 0xf4: /* +(a)-sup / -(c)- -(d) => inf-a/c */
  case 0xf5: /* +(a)-sup / -(c)-0 => inf-a/c */
    newmin = zmin;
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymin)));
    break;
  case 0x70: /* -(a)-sup / inf- -(d) => inf-a/d */
  case 0x74: /* -(a)-sup / -(c)- -(d) => inf-a/d */
    newmin = zmin;
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymax)));
    break;
  case 0x2e: /* inf- +(b) / +(c)- +(d) => inf-b/c */
  case 0x2f: /* inf- +(b) / +(c)-sup => inf-b/c */
    newmin = zmin;
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymin)));
    break;
  case 0xa: /* inf- -(b) / 0- +(d) => inf-b/d */
  case 0xe: /* inf- -(b) / +(c)- +(d) => inf-b/d */
    newmin = zmin;
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymax)));
    break;
  case 0xe1: /* +(a)- +(b) / inf-0 => -(b)- -1 */
    x_is_mon = 1;
    newmin = fd_safe_negate_val(xmax);
    newmax = TaggedMinusOne;
    break;
  case 0xe2: /* +(a)- +(b) / inf- +(d) => -(b)-b */
  case 0xe3: /* +(a)- +(b) / inf-sup => -(b)-b */
  case 0xe6: /* +(a)- +(b) / -(c)- +(d) => -(b)-b */
  case 0xe7: /* +(a)- +(b) / -(c)-sup => -(b)-b */
    x_is_mon = 1;
    newmin = fd_safe_negate_val(xmax);
    newmax = xmax;
    break;
  case 0xe5: /* +(a)- +(b) / -(c)-0 => -(b)-a/c */
    x_is_mon = 1;
    newmin = fd_safe_negate_val(xmax);
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymin)));
    break;
  case 0x4f: /* -(a)- -(b) / +(c)-sup => a/c- -1 */
    x_is_mon = 1;
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymin)));
    newmax = TaggedMinusOne;
    break;
  case 0x5e: /* -(a)-0 / +(c)- +(d) => a/c-0 */
  case 0x5f: /* -(a)-0 / +(c)-sup => a/c-0 */
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymin)));
    newmax = TaggedZero;
    break;
  case 0x7e: /* -(a)-sup / +(c)- +(d) => a/c-sup */
  case 0x7f: /* -(a)-sup / +(c)-sup => a/c-sup */
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymin)));
    newmax = zmax;
    break;
  case 0x6e: /* -(a)- +(b) / +(c)- +(d) => a/c-b/c */
  case 0x6f: /* -(a)- +(b) / +(c)-sup => a/c-b/c */
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymin)));
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymin)));
    break;
  case 0x4e: /* -(a)- -(b) / +(c)- +(d) => a/c-b/d */
    x_is_mon = 1;
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymin)));
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymax)));
    break;
  case 0xea: /* +(a)- +(b) / 0- +(d) => a/d-b */
    x_is_mon = 1;
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymax)));
    newmax = xmax;
    break;
  case 0xfa: /* +(a)-sup / 0- +(d) => a/d-sup */
  case 0xfe: /* +(a)-sup / +(c)- +(d) => a/d-sup */
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymax)));
    newmax = zmax;
    break;
  case 0xee: /* +(a)- +(b) / +(c)- +(d) => a/d-b/c */
    x_is_mon = 1;
    newmin = MakeSmall(CEILDIV(GetSmall(xmin),GetSmall(ymax)));
    newmax = MakeSmall(FLOORDIV(GetSmall(xmax),GetSmall(ymin)));
    break;
  case 0x4: /* inf- -(b) / -(c)- -(d) => b/c-sup */
  case 0x5: /* inf- -(b) / -(c)-0 => b/c-sup */
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymin)));
    newmax = zmax;
    break;
  case 0x45: /* -(a)- -(b) / -(c)-0 => b/c- -(a) */
    x_is_mon = 1;
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymin)));
    newmax = fd_safe_negate_val(xmin);
    break;
  case 0x44: /* -(a)- -(b) / -(c)- -(d) => b/c-a/d */
    x_is_mon = 1;
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymin)));
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymax)));
    break;
  case 0xa0: /* 0- +(b) / inf- -(d) => b/d-0 */
  case 0xa4: /* 0- +(b) / -(c)- -(d) => b/d-0 */
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymax)));
    newmax = TaggedZero;
    break;
  case 0xe0: /* +(a)- +(b) / inf- -(d) => b/d- -1 */
    x_is_mon = 1;
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymax)));
    newmax = TaggedMinusOne;
    break;
  case 0x20: /* inf- +(b) / inf- -(d) => b/d-sup */
  case 0x24: /* inf- +(b) / -(c)- -(d) => b/d-sup */
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymax)));
    newmax = zmax;
    break;
  case 0xe4: /* +(a)- +(b) / -(c)- -(d) => b/d-a/c */
    x_is_mon = 1;
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymax)));
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymin)));
    break;
  case 0x60: /* -(a)- +(b) / inf- -(d) => b/d-a/d */
  case 0x64: /* -(a)- +(b) / -(c)- -(d) => b/d-a/d */
    newmin = MakeSmall(-FLOORDIV(GetSmall(xmax),-GetSmall(ymax)));
    newmax = MakeSmall(-CEILDIV(GetSmall(xmin),-GetSmall(ymax)));
    break;
  default:
    return 2;
  }
  if (FDlt(newmin,zmin))
    newmin = zmin;
  if (FDgt(newmax,zmax))
    newmax = zmax;
  if (x_is_mon) {
    /* adjust newmin to ensure that it divides some X value,
       and similarly for newmax */
    long m = GetSmall(newmin);
    long n = GetSmall(newmax);
	
    while (m<=n && (m==0 || !is_supported_divider(m,xmin,xmax,ymin,ymax)))
      m++;
    while (m<=n && (n==0 || !is_supported_divider(n,xmin,xmax,ymin,ymax)))
      n--;
	
    newmin = MakeSmall(m);
    newmax = MakeSmall(n);
  }
  if (dvar_fix_interval_t(dvz, newmin, newmax)<0)
    return (newmin==Sup || newmax==Inf) ? -1 : 0;
  else
    return 1;
}

/*
  '$fd_product'(State0, State, Actions).
  State = state(X, XMut, Y, YMut, Z, ZMut)
*/
void SPCDECL
prolog_fd_product MAGIC (HIDDEN_PROTO
			 SP_term_ref State,
			 SP_term_ref NewState,
			 SP_term_ref Actions)
{
  WAMENV;
  Dvar dvx, dvy, dvz;
  TAGGED newmin, newmax;
  TAGGED handle;
  SP_BOOL committed;
  struct arith_data *pdata;
  int ent = -1;			/* disentailed unless otherwise */
  int iter;

  (void)State;                 /* [PM] 3.9b5 avoid -Wunused */
/*    X(0) = RefTerm(State0); */
  w->numstack_end = NULL;
  dvar_export_start(w);
  RefTerm(NewState) = fd_static_output_state(w,&handle,&committed);
  if (!IsVar(handle)) {		/* got [Flag | '$free'(Ptr)] */
    pdata = Pdata(struct arith_data,handle);
  } else {			/* build persistent state */
    pdata = Palloc(struct arith_data, 3*sizeof(struct dvar), handle);
    pdata->destructor = arith_destructor;
    pdata->nrefs = 6;
    FD_STORE_SPENV(pdata->spenv);
    pdata->refbase = SP_alloc_globrefs(6);
    pdata->dvar = (Dvar)(pdata+1);
    fd_get_var_and_attr(X(0),pdata->refbase);
    fd_get_var_and_attr(X(0)+WD(2),pdata->refbase+2);
    fd_get_var_and_attr(X(0)+WD(4),pdata->refbase+4);
  }

  /* RESUME HERE */
  dvx = pdata->dvar;
  dvy = dvx+1;
  dvz = dvx+2;
  dvar_init(dvx, pdata->refbase,   pdata->refbase+1);
  dvar_init(dvy, pdata->refbase+2, pdata->refbase+3);
  dvar_init(dvz, pdata->refbase+4, pdata->refbase+5);

  for (iter=0; iter<3; iter++)
    switch (iter) {
    case 0:			/* (X,Y) => Z */
      switch (ARITH_DISPATCH(xmin,xmax,ymin,ymax)) {
	/* automatically generated table! */
      case 0x9: /* inf- -(b) * 0-0 => 0-0 */
      case 0x19: /* inf-0 * 0-0 => 0-0 */
      case 0x29: /* inf- +(b) * 0-0 => 0-0 */
      case 0x39: /* inf-sup * 0-0 => 0-0 */
      case 0x49: /* -(a)- -(b) * 0-0 => 0-0 */
      case 0x59: /* -(a)-0 * 0-0 => 0-0 */
      case 0x69: /* -(a)- +(b) * 0-0 => 0-0 */
      case 0x79: /* -(a)-sup * 0-0 => 0-0 */
      case 0x90: /* 0-0 * inf- -(d) => 0-0 */
      case 0x91: /* 0-0 * inf-0 => 0-0 */
      case 0x92: /* 0-0 * inf- +(d) => 0-0 */
      case 0x93: /* 0-0 * inf-sup => 0-0 */
      case 0x94: /* 0-0 * -(c)- -(d) => 0-0 */
      case 0x95: /* 0-0 * -(c)-0 => 0-0 */
      case 0x96: /* 0-0 * -(c)- +(d) => 0-0 */
      case 0x97: /* 0-0 * -(c)-sup => 0-0 */
      case 0x99: /* 0-0 * 0-0 => 0-0 */
      case 0x9a: /* 0-0 * 0- +(d) => 0-0 */
      case 0x9b: /* 0-0 * 0-sup => 0-0 */
      case 0x9e: /* 0-0 * +(c)- +(d) => 0-0 */
      case 0x9f: /* 0-0 * +(c)-sup => 0-0 */
      case 0xa9: /* 0- +(b) * 0-0 => 0-0 */
      case 0xb9: /* 0-sup * 0-0 => 0-0 */
      case 0xe9: /* +(a)- +(b) * 0-0 => 0-0 */
      case 0xf9: /* +(a)-sup * 0-0 => 0-0 */
	newmin = TaggedZero;
	newmax = TaggedZero;
	break;
      case 0x1: /* inf- -(b) * inf-0 => 0-sup */
      case 0x5: /* inf- -(b) * -(c)-0 => 0-sup */
      case 0x10: /* inf-0 * inf- -(d) => 0-sup */
      case 0x11: /* inf-0 * inf-0 => 0-sup */
      case 0x14: /* inf-0 * -(c)- -(d) => 0-sup */
      case 0x15: /* inf-0 * -(c)-0 => 0-sup */
      case 0x41: /* -(a)- -(b) * inf-0 => 0-sup */
      case 0x50: /* -(a)-0 * inf- -(d) => 0-sup */
      case 0x51: /* -(a)-0 * inf-0 => 0-sup */
      case 0xab: /* 0- +(b) * 0-sup => 0-sup */
      case 0xaf: /* 0- +(b) * +(c)-sup => 0-sup */
      case 0xba: /* 0-sup * 0- +(d) => 0-sup */
      case 0xbb: /* 0-sup * 0-sup => 0-sup */
      case 0xbe: /* 0-sup * +(c)- +(d) => 0-sup */
      case 0xbf: /* 0-sup * +(c)-sup => 0-sup */
      case 0xeb: /* +(a)- +(b) * 0-sup => 0-sup */
      case 0xfa: /* +(a)-sup * 0- +(d) => 0-sup */
      case 0xfb: /* +(a)-sup * 0-sup => 0-sup */
	newmin = TaggedZero;
	newmax = zmax;
	break;
      case 0xaa: /* 0- +(b) * 0- +(d) => 0- +(b)* +(d) */
      case 0xae: /* 0- +(b) * +(c)- +(d) => 0- +(b)* +(d) */
      case 0xea: /* +(a)- +(b) * 0- +(d) => 0- +(b)* +(d) */
	newmin = TaggedZero;
	newmax = fd_safe_mul_val(xmax,ymax);
	break;
      case 0x45: /* -(a)- -(b) * -(c)-0 => 0- -(a)* -(c) */
      case 0x54: /* -(a)-0 * -(c)- -(d) => 0- -(a)* -(c) */
      case 0x55: /* -(a)-0 * -(c)-0 => 0- -(a)* -(c) */
	newmin = TaggedZero;
	newmax = fd_safe_mul_val(xmin,ymin);
	break;
      case 0xa: /* inf- -(b) * 0- +(d) => inf-0 */
      case 0xb: /* inf- -(b) * 0-sup => inf-0 */
      case 0x1a: /* inf-0 * 0- +(d) => inf-0 */
      case 0x1b: /* inf-0 * 0-sup => inf-0 */
      case 0x1e: /* inf-0 * +(c)- +(d) => inf-0 */
      case 0x1f: /* inf-0 * +(c)-sup => inf-0 */
      case 0x4b: /* -(a)- -(b) * 0-sup => inf-0 */
      case 0x5b: /* -(a)-0 * 0-sup => inf-0 */
      case 0x5f: /* -(a)-0 * +(c)-sup => inf-0 */
      case 0xa0: /* 0- +(b) * inf- -(d) => inf-0 */
      case 0xa1: /* 0- +(b) * inf-0 => inf-0 */
      case 0xb0: /* 0-sup * inf- -(d) => inf-0 */
      case 0xb1: /* 0-sup * inf-0 => inf-0 */
      case 0xb4: /* 0-sup * -(c)- -(d) => inf-0 */
      case 0xb5: /* 0-sup * -(c)-0 => inf-0 */
      case 0xe1: /* +(a)- +(b) * inf-0 => inf-0 */
      case 0xf1: /* +(a)-sup * inf-0 => inf-0 */
      case 0xf5: /* +(a)-sup * -(c)-0 => inf-0 */
	newmin = zmin;
	newmax = TaggedZero;
	break;
      case 0xe0: /* +(a)- +(b) * inf- -(d) => inf- +(a)* -(d) */
      case 0xf0: /* +(a)-sup * inf- -(d) => inf- +(a)* -(d) */
      case 0xf4: /* +(a)-sup * -(c)- -(d) => inf- +(a)* -(d) */
	newmin = zmin;
	newmax = fd_safe_mul_val(xmin,ymax);
	break;
      case 0x2a: /* inf- +(b) * 0- +(d) => inf- +(b)* +(d) */
      case 0x2e: /* inf- +(b) * +(c)- +(d) => inf- +(b)* +(d) */
      case 0xa2: /* 0- +(b) * inf- +(d) => inf- +(b)* +(d) */
      case 0xe2: /* +(a)- +(b) * inf- +(d) => inf- +(b)* +(d) */
	newmin = zmin;
	newmax = fd_safe_mul_val(xmax,ymax);
	break;
      case 0x47: /* -(a)- -(b) * -(c)-sup => inf- -(a)* -(c) */
      case 0x57: /* -(a)-0 * -(c)-sup => inf- -(a)* -(c) */
      case 0x74: /* -(a)-sup * -(c)- -(d) => inf- -(a)* -(c) */
      case 0x75: /* -(a)-sup * -(c)-0 => inf- -(a)* -(c) */
	newmin = zmin;
	newmax = fd_safe_mul_val(xmin,ymin);
	break;
      case 0xe: /* inf- -(b) * +(c)- +(d) => inf- -(b)* +(c) */
      case 0xf: /* inf- -(b) * +(c)-sup => inf- -(b)* +(c) */
      case 0x4f: /* -(a)- -(b) * +(c)-sup => inf- -(b)* +(c) */
	newmin = zmin;
	newmax = fd_safe_mul_val(xmax,ymin);
	break;
      case 0xef: /* +(a)- +(b) * +(c)-sup => +(a)* +(c)-sup */
      case 0xfe: /* +(a)-sup * +(c)- +(d) => +(a)* +(c)-sup */
      case 0xff: /* +(a)-sup * +(c)-sup => +(a)* +(c)-sup */
	newmin = fd_safe_mul_val(xmin,ymin);
	newmax = zmax;
	break;
      case 0xee: /* +(a)- +(b) * +(c)- +(d) => +(a)* +(c)- +(b)* +(d) */
	newmin = fd_safe_mul_val(xmin,ymin);
	newmax = fd_safe_mul_val(xmax,ymax);
	break;
      case 0xa4: /* 0- +(b) * -(c)- -(d) => +(b)* -(c)-0 */
      case 0xa5: /* 0- +(b) * -(c)-0 => +(b)* -(c)-0 */
      case 0xe5: /* +(a)- +(b) * -(c)-0 => +(b)* -(c)-0 */
	newmin = fd_safe_mul_val(xmax,ymin);
	newmax = TaggedZero;
	break;
      case 0x24: /* inf- +(b) * -(c)- -(d) => +(b)* -(c)-sup */
      case 0x25: /* inf- +(b) * -(c)-0 => +(b)* -(c)-sup */
      case 0xa7: /* 0- +(b) * -(c)-sup => +(b)* -(c)-sup */
      case 0xe7: /* +(a)- +(b) * -(c)-sup => +(b)* -(c)-sup */
	newmin = fd_safe_mul_val(xmax,ymin);
	newmax = zmax;
	break;
      case 0xe4: /* +(a)- +(b) * -(c)- -(d) => +(b)* -(c)- +(a)* -(d) */
	newmin = fd_safe_mul_val(xmax,ymin);
	newmax = fd_safe_mul_val(xmin,ymax);
	break;
      case 0xa6: /* 0- +(b) * -(c)- +(d) => +(b)* -(c)- +(b)* +(d) */
      case 0xe6: /* +(a)- +(b) * -(c)- +(d) => +(b)* -(c)- +(b)* +(d) */
	newmin = fd_safe_mul_val(xmax,ymin);
	newmax = fd_safe_mul_val(xmax,ymax);
	break;
      case 0x64: /* -(a)- +(b) * -(c)- -(d) => +(b)* -(c)- -(a)* -(c) */
      case 0x65: /* -(a)- +(b) * -(c)-0 => +(b)* -(c)- -(a)* -(c) */
	newmin = fd_safe_mul_val(xmax,ymin);
	newmax = fd_safe_mul_val(xmin,ymin);
	break;
      case 0x4a: /* -(a)- -(b) * 0- +(d) => -(a)* +(d)-0 */
      case 0x5a: /* -(a)-0 * 0- +(d) => -(a)* +(d)-0 */
      case 0x5e: /* -(a)-0 * +(c)- +(d) => -(a)* +(d)-0 */
	newmin = fd_safe_mul_val(xmin,ymax);
	newmax = TaggedZero;
	break;
      case 0x42: /* -(a)- -(b) * inf- +(d) => -(a)* +(d)-sup */
      case 0x52: /* -(a)-0 * inf- +(d) => -(a)* +(d)-sup */
      case 0x7a: /* -(a)-sup * 0- +(d) => -(a)* +(d)-sup */
      case 0x7e: /* -(a)-sup * +(c)- +(d) => -(a)* +(d)-sup */
	newmin = fd_safe_mul_val(xmin,ymax);
	newmax = zmax;
	break;
      case 0x6a: /* -(a)- +(b) * 0- +(d) => -(a)* +(d)- +(b)* +(d) */
      case 0x6e: /* -(a)- +(b) * +(c)- +(d) => -(a)* +(d)- +(b)* +(d) */
	newmin = fd_safe_mul_val(xmin,ymax);
	newmax = fd_safe_mul_val(xmax,ymax);
	break;
      case 0x46: /* -(a)- -(b) * -(c)- +(d) => -(a)* +(d)- -(a)* -(c) */
      case 0x56: /* -(a)-0 * -(c)- +(d) => -(a)* +(d)- -(a)* -(c) */
	newmin = fd_safe_mul_val(xmin,ymax);
	newmax = fd_safe_mul_val(xmin,ymin);
	break;
      case 0x4e: /* -(a)- -(b) * +(c)- +(d) => -(a)* +(d)- -(b)* +(c) */
	newmin = fd_safe_mul_val(xmin,ymax);
	newmax = fd_safe_mul_val(xmax,ymin);
	break;
      case 0x0: /* inf- -(b) * inf- -(d) => -(b)* -(d)-sup */
      case 0x4: /* inf- -(b) * -(c)- -(d) => -(b)* -(d)-sup */
      case 0x40: /* -(a)- -(b) * inf- -(d) => -(b)* -(d)-sup */
	newmin = fd_safe_mul_val(xmax,ymax);
	newmax = zmax;
	break;
      case 0x44: /* -(a)- -(b) * -(c)- -(d) => -(b)* -(d)- -(a)* -(c) */
	newmin = fd_safe_mul_val(xmax,ymax);
	newmax = fd_safe_mul_val(xmin,ymin);
	break;
      case 0x66: /* -(a)- +(b) * -(c)- +(d) => min(-(a)* +(d),+(b)* -(c))-max(-(a)* -(c),+(b)* +(d)) */
	{
	  TAGGED minmax = fd_safe_mul_val(xmin,ymax);
	  TAGGED maxmin = fd_safe_mul_val(xmax,ymin);
	  TAGGED minmin = fd_safe_mul_val(xmin,ymin);
	  TAGGED maxmax = fd_safe_mul_val(xmax,ymax);

	  newmin = FDgt(minmax,maxmin) ? maxmin : minmax;
	  newmax = FDgt(minmin,maxmax) ? minmin : maxmax;
	}
	break;
      default:
	continue;
      }
      if (dvar_fix_interval_t(dvz, newmin, newmax)<0) {
	if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	  goto oflo;
	goto ret;
      }
      break;
    case 1:			/* (X,Y) => X */
      switch (fd_product_inverse_dispatch(dvz, dvy, dvx)) {
      case -1: goto oflo;
      case 0: goto ret;
      }
      break;
    case 2:		/* (Z,X) => Y */
      switch (fd_product_inverse_dispatch(dvz, dvx, dvy)) {
      case -1: goto oflo;
      case 0: goto ret;
      }
      break;
    }

  dvar_export(w,dvx);
  dvar_export(w,dvy);
  dvar_export(w,dvz);
  ent = (dvar_is_integer(dvx) &&
 	 dvar_is_integer(dvy) &&
 	 dvar_is_integer(dvz));
/*   ent = (!dvar_is_integer_first(dvx) + */
/* 	 !dvar_is_integer_first(dvy) + */
/* 	 !dvar_is_integer_first(dvz) <= 1); */
  goto ret;
 oflo:
  fd.fd_overflow = TRUE;
 ret:
  if (ent==1)
    Pfree;
  dvar_export_done(w,Actions, ent);
}

#if 0

/* Can be linear in the size of some domain.
   Can be wrong, witness SPRM 11282:

   | ?- domain([T,I,Q], -100000,32000000),T#=((I*Q))/100.

   T in-100000..2684354,

   I in-100000..32000000,

   Q in-100000..32000000 ?

*/

static TAGGED fast_div(TAGGED t1, TAGGED t2)
{
  return MakeSmall(GetSmall(t1)/GetSmall(t2));
}

static TAGGED fast_mod(TAGGED t1, TAGGED t2)
{
  long dividend = GetSmall(t1);
  long divisor  = GetSmall(t2);
  long value = dividend % divisor;
  if (value != 0 && (value < 0) != (divisor < 0))
    value += divisor;
  return MakeSmall(value);
}

static TAGGED fast_rem(TAGGED t1, TAGGED t2)
{
  return MakeSmall(GetSmall(t1)%GetSmall(t2));
}

#define is_bound_consistent(A1,A2,A3,A4,A5) is_bound_consistent(HIDDEN_ARG, A1,A2,A3,A4,A5) 
#define shave_bounds(A1,A2,A3) shave_bounds(HIDDEN_ARG, A1,A2,A3) 
static SP_BOOL
is_bound_consistent MAGIC (HIDDEN_PROTO
			   Argdecl,
			   Dvar dvx,
			   int i,  /* 0=x, 1=y, 2=z */
			   int op, /* 0=div, 1=mod, 2=rem */
			   TAGGED val)
{
  TAGGED x = i==0 ? val : dvar_min_t(dvx+0);
  TAGGED y = i==1 ? val : dvar_min_t(dvx+1);
  TAGGED z = i==2 ? val : dvar_min_t(dvx+2);
  TAGGED ax, ay, az, newmin=0, newmax=0, support=0;
  int key, ground=0;

  if (i==1 && y==TaggedZero)
    return TRUE;

  key = ((i==0 || dvar_is_integer(dvx+0))<<0)+
        ((i==1 || dvar_is_integer(dvx+1))<<1)+
        ((i==2 || dvar_is_integer(dvx+2))<<2);
  
  switch (key) {
  case 3:
    i = 2;
    support = dvar_set(dvx+2, w);
    break;
  case 5:
    i = 1;
    support = dvar_set(dvx+1, w);
    break;
  case 6:
    i = 0;
    support = dvar_set(dvx+0, w);
    break;
  case 7:
    ground = 1;
    i = 2;
    break;
  default:
    return TRUE;
  }
  switch (3*op+i) {
   case 0:
    ay = (Tgez(y) ? y : fd_safe_negate_val(y));
    az = (Tgez(z) ? z : fd_safe_negate_val(z));
    /* AUTOMATICALLY GENERATED CASES FOR div SHAVING, CHECKING DVAR dvx */
    if (Tlt(y,TaggedZero)) {
      if (Tlt(z,TaggedZero)) {
        newmin = fd_safe_mul(ay,az);
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(ay,az),ay),MakeSmall(1));
      } else if (Teq(z,TaggedZero)) {
        newmax = fd_safe_minus(ay,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
      } else {
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(ay,az),ay));
        newmax = fd_safe_negate(fd_safe_mul(ay,az));
      }
    } else if (Tlt(z,TaggedZero)) {
      newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(ay,az),ay));
      newmax = fd_safe_negate(fd_safe_mul(ay,az));
    } else if (Teq(z,TaggedZero)) {
      newmax = fd_safe_minus(ay,MakeSmall(1));
      newmin = fd_safe_negate(newmax);
    } else {
      newmin = fd_safe_mul(ay,az);
      newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(ay,az),ay),MakeSmall(1));
    }
    break;

   case 1:
    ax = (Tgez(x) ? x : fd_safe_negate_val(x));
    az = (Tgez(z) ? z : fd_safe_negate_val(z));
    /* AUTOMATICALLY GENERATED CASES FOR div SHAVING, CHECKING DVAR dvy */
    if (Tlt(x,TaggedZero)) {
      if (Tlt(z,TaggedZero)) {
        newmin = fd_safe_divu(fd_safe_plus(ax,MakeSmall(1)),fd_safe_plus(az,MakeSmall(1)));
        newmax = fd_safe_divd(ax,az);
      } else if (Tgt(z,TaggedZero)) {
        newmin = fd_safe_negate(fd_safe_divd(ax,az));
        newmax = fd_safe_negate(fd_safe_divu(fd_safe_plus(ax,MakeSmall(1)),fd_safe_plus(az,MakeSmall(1))));
      } else {
        newmin = fd_safe_negate(ax);
        newmax = ax;
        support = fd_subtract_interval(w,support,newmin,newmax);
        if (support==EmptySet)
          goto ret;
        return TRUE;
      }
    } else if (Teq(x,TaggedZero)) {
      if (Tne(z,TaggedZero)) {
        goto ret;
      } else {
        return TRUE;
      }
    } else if (Tlt(z,TaggedZero)) {
      newmin = fd_safe_negate(fd_safe_divd(ax,az));
      newmax = fd_safe_negate(fd_safe_divu(fd_safe_plus(ax,MakeSmall(1)),fd_safe_plus(az,MakeSmall(1))));
    } else {
      if (Tgt(z,TaggedZero)) {
        newmin = fd_safe_divu(fd_safe_plus(ax,MakeSmall(1)),fd_safe_plus(az,MakeSmall(1)));
        newmax = fd_safe_divd(ax,az);
      } else {
        newmin = fd_safe_negate(ax);
        newmax = ax;
        support = fd_subtract_interval(w,support,newmin,newmax);
        if (support==EmptySet)
          goto ret;
        return TRUE;
      }
    }
    break;

   case 2:
    /* AUTOMATICALLY GENERATED CASES FOR div SHAVING, CHECKING DVAR dvz */
    newmin = newmax = fast_div(x,y);
    break;

   case 3:
    ay = (Tgez(y) ? y : fd_safe_negate_val(y));
    az = (Tgez(z) ? z : fd_safe_negate_val(z));
    /* AUTOMATICALLY GENERATED CASES FOR mod SHAVING, CHECKING DVAR dvx */
    if (Tlt(y,TaggedZero)) {
      if (Tlt(z,TaggedZero)) {
        newmin = TaggedZero;
        newmax = newmin;
        support = fd_subtract_interval(w,support,newmin,newmax);
        if (support==EmptySet)
          goto ret;
        return TRUE;
      } else if (Teq(z,TaggedZero)) {
        return TRUE;
      } else {
        goto ret;
      }
    } else if (Tlt(z,TaggedZero)) {
      goto ret;
    } else if (Teq(z,TaggedZero)) {
      return TRUE;
    } else {
      newmin = TaggedZero;
      newmax = newmin;
      support = fd_subtract_interval(w,support,newmin,newmax);
      if (support==EmptySet)
        goto ret;
      return TRUE;
    }
    break;

   case 4:
    ax = (Tgez(x) ? x : fd_safe_negate_val(x));
    az = (Tgez(z) ? z : fd_safe_negate_val(z));
    /* AUTOMATICALLY GENERATED CASES FOR mod SHAVING, CHECKING DVAR dvy */
    if (Tlt(x,TaggedZero)) {
      if (Tlt(z,TaggedZero)) {
        if (Teq(ax,az)) {
          newmin = fd_safe_negate(ax);
          newmax = fd_safe_negate(fd_safe_plus(fd_safe_minus(ax,az),MakeSmall(1)));
          support = fd_subtract_interval(w,support,newmin,newmax);
          if (support==EmptySet)
            goto ret;
          newmin = Inf;
          newmax = fd_safe_negate(fd_safe_plus(az,MakeSmall(1)));
        } else {
          newmin = fd_safe_minus(az,ax);
          newmax = fd_safe_negate(fd_safe_plus(az,MakeSmall(1)));
        }
      } else if (Tgt(z,TaggedZero)) {
        newmin = fd_safe_plus(az,MakeSmall(1));
        newmax = fd_safe_plus(ax,az);
      } else {
        newmin = fd_safe_negate(ax);
        newmax = ax;
      }
    } else if (Teq(x,TaggedZero)) {
      if (Tne(z,TaggedZero)) {
        goto ret;
      } else {
        return TRUE;
      }
    } else if (Tlt(z,TaggedZero)) {
      newmin = fd_safe_negate(fd_safe_plus(ax,az));
      newmax = fd_safe_negate(fd_safe_plus(az,MakeSmall(1)));
    } else {
      if (Tgt(z,TaggedZero)) {
        if (Teq(ax,az)) {
          newmin = fd_safe_plus(fd_safe_minus(ax,az),MakeSmall(1));
          newmax = ax;
          support = fd_subtract_interval(w,support,newmin,newmax);
          if (support==EmptySet)
            goto ret;
          newmin = fd_safe_plus(az,MakeSmall(1));
          newmax = Sup;
        } else {
          newmin = fd_safe_plus(az,MakeSmall(1));
          newmax = fd_safe_minus(ax,az);
        }
      } else {
        newmin = fd_safe_negate(ax);
        newmax = ax;
      }
    }
    break;

   case 5:
    /* AUTOMATICALLY GENERATED CASES FOR mod SHAVING, CHECKING DVAR dvz */
    newmin = newmax = fast_mod(x,y);
    break;

   case 6:
    ay = (Tgez(y) ? y : fd_safe_negate_val(y));
    az = (Tgez(z) ? z : fd_safe_negate_val(z));
    /* AUTOMATICALLY GENERATED CASES FOR rem SHAVING, CHECKING DVAR dvx */
    if (Tlt(z,TaggedZero)) {
      newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(ay,az));
      newmax = fd_safe_negate(fd_safe_plus(az,MakeSmall(1)));
      support = fd_subtract_interval(w,support,newmin,newmax);
      if (support==EmptySet)
        goto ret;
      newmin = Inf;
      newmax = fd_safe_negate(az);
    } else if (Teq(z,TaggedZero)) {
      newmin = MakeSmall(1);
      newmax = fd_safe_minus(ay,MakeSmall(1));
      support = fd_subtract_interval(w,support,newmin,newmax);
      if (support==EmptySet)
        goto ret;
      newmin = fd_safe_minus(MakeSmall(1),ay);
      newmax = MakeSmall(-1);
      support = fd_subtract_interval(w,support,newmin,newmax);
      if (support==EmptySet)
        goto ret;
      return TRUE;
    } else {
      newmin = fd_safe_plus(az,MakeSmall(1));
      newmax = fd_safe_minus(fd_safe_plus(ay,az),MakeSmall(1));
      support = fd_subtract_interval(w,support,newmin,newmax);
      if (support==EmptySet)
        goto ret;
      newmin = az;
      newmax = Sup;
    }
    break;

   case 7:
    ax = (Tgez(x) ? x : fd_safe_negate_val(x));
    az = (Tgez(z) ? z : fd_safe_negate_val(z));
    /* AUTOMATICALLY GENERATED CASES FOR rem SHAVING, CHECKING DVAR dvy */
    if (Tlt(x,TaggedZero)) {
      if (Tlt(z,TaggedZero)) {
        newmin = fd_safe_negate(az);
        newmax = az;
        support = fd_subtract_interval(w,support,newmin,newmax);
        if (support==EmptySet)
          goto ret;
        if (Teq(ax,az)) {
          return TRUE;
        } else {
          newmax = fd_safe_minus(ax,az);
          newmin = fd_safe_negate(newmax);
        }
      } else if (Tgt(z,TaggedZero)) {
        goto ret;
      } else {
        newmin = fd_safe_negate(ax);
        newmax = ax;
      }
    } else if (Teq(x,TaggedZero)) {
      if (Tne(z,TaggedZero)) {
        goto ret;
      } else {
        return TRUE;
      }
    } else if (Tlt(z,TaggedZero)) {
      goto ret;
    } else {
      if (Tgt(z,TaggedZero)) {
        newmin = fd_safe_negate(az);
        newmax = az;
        support = fd_subtract_interval(w,support,newmin,newmax);
        if (support==EmptySet)
          goto ret;
        if (Teq(ax,az)) {
          return TRUE;
        } else {
          newmax = fd_safe_minus(ax,az);
          newmin = fd_safe_negate(newmax);
        }
      } else {
        newmin = fd_safe_negate(ax);
        newmax = ax;
      }
    }
    break;

   case 8:
    /* AUTOMATICALLY GENERATED CASES FOR rem SHAVING, CHECKING DVAR dvz */
    newmin = newmax = fast_rem(x,y);
    break;
  }
  if (ground) {
    if (newmin==z)
      return TRUE;
  } else {
    if (FDle(newmin,newmax) && support!=EmptySet && fd_compare_interval(support,newmin,newmax)!=FDI_DISJOINT)
      return TRUE;
  }
 ret:
  return FALSE;
}

static SP_BOOL
shave_bounds MAGIC(HIDDEN_PROTO
		   Argdecl,
		   Dvar dvx,
		   int op)
{
  int i;
  for (i=0; i<3; i++) {
    {
      TAGGED t = dvar_min_t(dvx+i);
      while (TagIsSmall(t) && !is_bound_consistent(w,dvx,i,op,t)) { 
	if (dvar_prune_value_t(dvx+i,t,w)<0)
	  return FALSE;
	t = dvar_min_t(dvx+i);
      }
    }
    if (!dvar_is_integer(dvx+i)) {
      TAGGED t = dvar_max_t(dvx+i);
      while (TagIsSmall(t) && !is_bound_consistent(w,dvx,i,op,t)) { 
	if (dvar_prune_value_t(dvx+i,t,w)<0)
	  return FALSE;
	t = dvar_max_t(dvx+i);
      }
    }
  }
  return TRUE;
}
#endif

static SP_BOOL
plan_divmodrem MAGIC(HIDDEN_PROTO
		     struct arith_data *pdata,
		     Argdecl)
{
  Dvar dvx = pdata->dvar;
  int i;
  
  for (i=0; i<3; i++)
    dvar_init(dvx+i, pdata->refbase+2*i,   pdata->refbase+2*i+1);

  if (dvar_prune_value_l(dvx+1,0,w)<0)
    return FALSE;
  return TRUE;
}

static int
dvar_fix_min_safe MAGIC(HIDDEN_PROTO
			Dvar dv, long lb)
{
  if (IntIsSmall(lb))
    return dvar_fix_min_l(dv,lb);
  else {
    fd.fd_overflow = TRUE;
    return -1;
  }
}

static int
dvar_fix_max_safe MAGIC(HIDDEN_PROTO
			Dvar dv, long lb)
{
  if (IntIsSmall(lb))
    return dvar_fix_max_l(dv,lb);
  else {
    fd.fd_overflow = TRUE;
    return -1;
  }
}

static SP_BOOL
mod_integer MAGIC(HIDDEN_PROTO
		  struct arith_data *pdata,
		  Argdecl)
{
  Dvar dvx = pdata->dvar;
  long c = dvar_min_l(dvx+1);
  int notinf = TagIsSmall(dvar_min_t(dvx+0));
  int notsup = TagIsSmall(dvar_max_t(dvx+0));
  int rc = 0;

  if (c==0)
    rc = FALSE;
  else if (c>0) {
    long xi = dvar_max_l(dvx+0) - dvar_min_l(dvx+0) + 1;
    long xminc = fast_modi(dvar_min_l(dvx+0),c);
    long xmaxc = fast_modi(dvar_max_l(dvx+0),c);

    if (!notinf || !notsup || xi>=c)
      rc |= dvar_fix_interval_l(dvx+2,0,(c-1));
    else if (xminc <= xmaxc)
      rc |= dvar_fix_interval_l(dvx+2,(xminc),(xmaxc));
    else {
      rc &= dvar_prune_interval_l(dvx+2,(xmaxc+1),(xminc-1),w);
      rc &= dvar_fix_interval_l(dvx+2,0,(c-1));
    }

    if (notinf) {
      long q = (dvar_min_l(dvx+0)-xminc)/c;
      if (xminc<dvar_min_l(dvx+2))
	rc |= dvar_fix_min_safe(dvx+0,(c*q+dvar_min_l(dvx+2)));
      else if (xminc>dvar_max_l(dvx+2))
	rc |= dvar_fix_min_safe(dvx+0,(c*(q+1)+dvar_min_l(dvx+2)));
    }
    if (notsup) {
      long q = (dvar_max_l(dvx+0)-xmaxc)/c;
      if (xmaxc>dvar_max_l(dvx+2))
	rc |= dvar_fix_max_safe(dvx+0,(c*q+dvar_max_l(dvx+2)));
      else if (xmaxc<dvar_min_l(dvx+2))
	rc |= dvar_fix_max_safe(dvx+0,(c*(q-1)+dvar_max_l(dvx+2)));
    }
  } else {
    long xi = dvar_max_l(dvx+0) - dvar_min_l(dvx+0) + 1;
    long xminc = fast_modi(dvar_min_l(dvx+0),c);
    long xmaxc = fast_modi(dvar_max_l(dvx+0),c);

    if (!notinf || !notsup || xi>=-c)
      rc |= dvar_fix_interval_l(dvx+2,(c+1),0);
    else if (xminc <= xmaxc)
      rc |= dvar_fix_interval_l(dvx+2,(xminc),(xmaxc));
    else {
      rc &= dvar_prune_interval_l(dvx+2,(xmaxc+1),(xminc-1),w);
      rc &= dvar_fix_interval_l(dvx+2,(c+1),0);
    }

    if (notinf) {
      long q = (dvar_min_l(dvx+0)-xminc)/c;
      if (xminc<dvar_min_l(dvx+2))
	rc |= dvar_fix_min_safe(dvx+0,(c*q+dvar_min_l(dvx+2)));
      else if (xminc>dvar_max_l(dvx+2))
	rc |= dvar_fix_min_safe(dvx+0,(c*(q-1)+dvar_min_l(dvx+2)));
    }
    if (notsup) {
      long q = (dvar_max_l(dvx+0)-xmaxc)/c;
      if (xmaxc>dvar_max_l(dvx+2))
	rc |= dvar_fix_max_safe(dvx+0,(c*q+dvar_max_l(dvx+2)));
      else if (xmaxc<dvar_min_l(dvx+2))
	rc |= dvar_fix_max_safe(dvx+0,(c*(q+1)+dvar_max_l(dvx+2)));
    }
  }
  return rc>=0;
}

static SP_BOOL
rem_integer MAGIC(HIDDEN_PROTO
		  struct arith_data *pdata,
		  Argdecl)
{
  Dvar dvx = pdata->dvar;
  long c = dvar_min_l(dvx+1);
  long uc = (c > 0 ? c : -c);
  int notinf = TagIsSmall(dvar_min_t(dvx+0));
  int notsup = TagIsSmall(dvar_max_t(dvx+0));
  int rc = 0;

  if (c==0) {
    rc = -1;
  } else {
    long xi = dvar_max_l(dvx+0) - dvar_min_l(dvx+0) + 1;
    long xminc = dvar_min_l(dvx+0) % uc;
    long xmaxc = dvar_max_l(dvx+0) % uc;
  
    /* prune Z */
    if ((!notinf || dvar_min_l(dvx+0)<=0) && (!notsup || dvar_max_l(dvx+0)>=0)) {
      long lb = ((notinf && dvar_min_l(dvx+0) > -uc) ? dvar_min_l(dvx+0) : -uc+1);
      long ub = ((notsup && dvar_max_l(dvx+0) <  uc) ? dvar_max_l(dvx+0) :  uc-1);
      rc |= dvar_fix_interval_l(dvx+2,(lb),(ub));
    } else if (!notsup || dvar_max_l(dvx+0)>=0) {
      if (!notsup || xi>=uc)
	rc |= dvar_fix_interval_l(dvx+2,0,(uc-1));
      else if (xminc <= xmaxc)
	rc |= dvar_fix_interval_l(dvx+2,(xminc),(xmaxc));
      else {
	rc &= dvar_prune_interval_l(dvx+2,(xmaxc+1),(xminc-1),w);
	rc &= dvar_fix_interval_l(dvx+2,0,(uc-1));
      }
    } else {
      if (!notinf || xi>=uc)
	rc |= dvar_fix_interval_l(dvx+2,(-uc+1),0);
      else if (xminc <= xmaxc)
	rc |= dvar_fix_interval_l(dvx+2,(xminc),(xmaxc));
      else {
	rc &= dvar_prune_interval_l(dvx+2,(xmaxc+1),(xminc-1),w);
	rc &= dvar_fix_interval_l(dvx+2,(-uc+1),0);
      }
    }

    /* prune X */
    if (notinf) {
      long q = dvar_min_l(dvx+0)/c;
      if (xminc<dvar_min_l(dvx+2))
	rc |= dvar_fix_min_safe(dvx+0,(c*q+dvar_min_l(dvx+2)));
      else if (xminc>dvar_max_l(dvx+2))
	rc |= dvar_fix_min_safe(dvx+0,(c*(q+1)+dvar_min_l(dvx+2)));
    }
    if (notsup) {
      long q = dvar_max_l(dvx+0)/c;
      if (xmaxc>dvar_max_l(dvx+2))
	rc |= dvar_fix_max_safe(dvx+0,(c*q+dvar_max_l(dvx+2)));
      else if (xmaxc<dvar_min_l(dvx+2))
	rc |= dvar_fix_max_safe(dvx+0,(c*(q-1)+dvar_max_l(dvx+2)));
    }
  }
  return rc>=0;
}


/*
  '$fd_quotient'(State0, State, Actions).
  State = state(X-XMut, Y-YMut, Z-ZMut, B-Bmut)
  Z #= X/Y AND (Y=0 implies B=0)
*/
void SPCDECL
prolog_fd_quotient MAGIC (HIDDEN_PROTO
			  SP_term_ref State,
			  SP_term_ref NewState,
			  SP_term_ref Actions)
{
  WAMENV;
  Dvar dvx, dvy, dvz;
  TAGGED newmin, newmax, axmin, axmax, aymin, aymax, azmin, azmax;
  int i, iter;
  TAGGED handle, t1;
  SP_BOOL committed;
  struct arith_data *pdata;
  int ent = -1;			/* disentailed unless otherwise */

  (void)State;                 /* [PM] 3.9b5 avoid -Wunused */
/*    X(0) = RefTerm(State0); */
  w->numstack_end = NULL;
  dvar_export_start(w);
  RefTerm(NewState) = fd_static_output_state(w,&handle,&committed);
  if (!IsVar(handle)) {		/* got [Flag | '$free'(Ptr)] */
    pdata = Pdata(struct arith_data,handle);
  } else {			/* build persistent state */
    pdata = Palloc(struct arith_data, 4*sizeof(struct dvar), handle);
    pdata->destructor = arith_destructor;
    pdata->nrefs = 6;
    FD_STORE_SPENV(pdata->spenv);
    pdata->refbase = SP_alloc_globrefs(6);
    pdata->dvar = (Dvar)(pdata+1);
    for (i=0; i<3; i++) {
      DerefArg(t1,X(0),i+1);
      fd_get_var_and_attr(t1,pdata->refbase+2*i);
    }
  }

  /* RESUME HERE */
  dvx = pdata->dvar;
  dvy = dvx+1;
  dvz = dvx+2;
  if (!plan_divmodrem(pdata,w))
    goto ret;
  for (iter=0; iter<3; iter++) {
    switch (iter) {
    case 0:			/* (X,Y) => Z */
      axmin = (Tgez(xmin) ? xmin : fd_safe_negate_val(xmin));
      axmax = (Tgez(xmax) ? xmax : fd_safe_negate_val(xmax));
      aymin = (Tgez(ymin) ? ymin : fd_safe_negate_val(ymin));
      aymax = (Tgez(ymax) ? ymax : fd_safe_negate_val(ymax));
      switch (ARITH_DISPATCH(xmin,xmax,ymin,ymax)) {
        /* AUTOMATICALLY GENERATED CASES FOR div PRUNING DVAR dvz */
      case 0x9: /* inf..-(axmax) * 0..0 */
      case 0x49: /* -(axmin)..-(axmax) * 0..0 */
      case 0x19: /* inf..0 * 0..0 */
      case 0x59: /* -(axmin)..0 * 0..0 */
      case 0x29: /* inf..+(axmax) * 0..0 */
      case 0x39: /* inf..sup * 0..0 */
      case 0x69: /* -(axmin)..+(axmax) * 0..0 */
      case 0x79: /* -(axmin)..sup * 0..0 */
      case 0x99: /* 0..0 * 0..0 */
      case 0xa9: /* 0..+(axmax) * 0..0 */
      case 0xb9: /* 0..sup * 0..0 */
      case 0xe9: /* +(axmin)..+(axmax) * 0..0 */
      case 0xf9: /* +(axmin)..sup * 0..0 */
        goto ret;
      case 0x12: /* inf..0 * inf..+(aymax) */
      case 0x13: /* inf..0 * inf..sup */
      case 0x16: /* inf..0 * -(aymin)..+(aymax) */
      case 0x17: /* inf..0 * -(aymin)..sup */
      case 0x30: /* inf..sup * inf..-(aymax) */
      case 0x34: /* inf..sup * -(aymin)..-(aymax) */
      case 0x31: /* inf..sup * inf..0 */
      case 0x35: /* inf..sup * -(aymin)..0 */
      case 0x22: /* inf..+(axmax) * inf..+(aymax) */
      case 0x23: /* inf..+(axmax) * inf..sup */
      case 0x26: /* inf..+(axmax) * -(aymin)..+(aymax) */
      case 0x27: /* inf..+(axmax) * -(aymin)..sup */
      case 0x32: /* inf..sup * inf..+(aymax) */
      case 0x33: /* inf..sup * inf..sup */
      case 0x36: /* inf..sup * -(aymin)..+(aymax) */
      case 0x37: /* inf..sup * -(aymin)..sup */
      case 0x72: /* -(axmin)..sup * inf..+(aymax) */
      case 0x73: /* -(axmin)..sup * inf..sup */
      case 0x76: /* -(axmin)..sup * -(aymin)..+(aymax) */
      case 0x77: /* -(axmin)..sup * -(aymin)..sup */
      case 0x3a: /* inf..sup * 0..+(aymax) */
      case 0x3b: /* inf..sup * 0..sup */
      case 0x3e: /* inf..sup * +(aymin)..+(aymax) */
      case 0x3f: /* inf..sup * +(aymin)..sup */
      case 0xb2: /* 0..sup * inf..+(aymax) */
      case 0xb3: /* 0..sup * inf..sup */
      case 0xb6: /* 0..sup * -(aymin)..+(aymax) */
      case 0xb7: /* 0..sup * -(aymin)..sup */
      default:
        continue;
      case 0x90: /* 0..0 * inf..-(aymax) */
      case 0x94: /* 0..0 * -(aymin)..-(aymax) */
      case 0x91: /* 0..0 * inf..0 */
      case 0x95: /* 0..0 * -(aymin)..0 */
      case 0x92: /* 0..0 * inf..+(aymax) */
      case 0x93: /* 0..0 * inf..sup */
      case 0x96: /* 0..0 * -(aymin)..+(aymax) */
      case 0x97: /* 0..0 * -(aymin)..sup */
      case 0x9a: /* 0..0 * 0..+(aymax) */
      case 0x9b: /* 0..0 * 0..sup */
      case 0x9e: /* 0..0 * +(aymin)..+(aymax) */
      case 0x9f: /* 0..0 * +(aymin)..sup */
        newmin = TaggedZero;
        newmax = newmin;
        break;
      case 0xaa: /* 0..+(axmax) * 0..+(aymax) */
      case 0xab: /* 0..+(axmax) * 0..sup */
      case 0xeb: /* +(axmin)..+(axmax) * 0..sup */
        newmin = TaggedZero;
        newmax = axmax;
        break;
      case 0x41: /* -(axmin)..-(axmax) * inf..0 */
      case 0x51: /* -(axmin)..0 * inf..0 */
      case 0x55: /* -(axmin)..0 * -(aymin)..0 */
        newmin = TaggedZero;
        newmax = axmin;
        break;
      case 0x0: /* inf..-(axmax) * inf..-(aymax) */
      case 0x1: /* inf..-(axmax) * inf..0 */
      case 0x10: /* inf..0 * inf..-(aymax) */
      case 0x14: /* inf..0 * -(aymin)..-(aymax) */
      case 0x11: /* inf..0 * inf..0 */
      case 0x15: /* inf..0 * -(aymin)..0 */
      case 0xba: /* 0..sup * 0..+(aymax) */
      case 0xbb: /* 0..sup * 0..sup */
      case 0xbe: /* 0..sup * +(aymin)..+(aymax) */
      case 0xbf: /* 0..sup * +(aymin)..sup */
      case 0xfb: /* +(axmin)..sup * 0..sup */
      case 0xff: /* +(axmin)..sup * +(aymin)..sup */
        newmin = TaggedZero;
        newmax = Sup;
        break;
      case 0xae: /* 0..+(axmax) * +(aymin)..+(aymax) */
      case 0xaf: /* 0..+(axmax) * +(aymin)..sup */
      case 0xef: /* +(axmin)..+(axmax) * +(aymin)..sup */
        newmin = TaggedZero;
        newmax = fd_safe_divd(axmax,aymin);
        break;
      case 0x40: /* -(axmin)..-(axmax) * inf..-(aymax) */
      case 0x50: /* -(axmin)..0 * inf..-(aymax) */
      case 0x54: /* -(axmin)..0 * -(aymin)..-(aymax) */
        newmin = TaggedZero;
        newmax = fd_safe_divd(axmin,aymax);
        break;
      case 0x45: /* -(axmin)..-(axmax) * -(aymin)..0 */
        newmin = fd_safe_divd(axmax,aymin);
        newmax = axmin;
        break;
      case 0x4: /* inf..-(axmax) * -(aymin)..-(aymax) */
      case 0x5: /* inf..-(axmax) * -(aymin)..0 */
        newmin = fd_safe_divd(axmax,aymin);
        newmax = Sup;
        break;
      case 0x44: /* -(axmin)..-(axmax) * -(aymin)..-(aymax) */
        newmin = fd_safe_divd(axmax,aymin);
        newmax = fd_safe_divd(axmin,aymax);
        break;
      case 0xea: /* +(axmin)..+(axmax) * 0..+(aymax) */
        newmin = fd_safe_divd(axmin,aymax);
        newmax = axmax;
        break;
      case 0xfa: /* +(axmin)..sup * 0..+(aymax) */
      case 0xfe: /* +(axmin)..sup * +(aymin)..+(aymax) */
        newmin = fd_safe_divd(axmin,aymax);
        newmax = Sup;
        break;
      case 0xee: /* +(axmin)..+(axmax) * +(aymin)..+(aymax) */
        newmin = fd_safe_divd(axmin,aymax);
        newmax = fd_safe_divd(axmax,aymin);
        break;
      case 0xa1: /* 0..+(axmax) * inf..0 */
      case 0xa5: /* 0..+(axmax) * -(aymin)..0 */
      case 0xe1: /* +(axmin)..+(axmax) * inf..0 */
        newmin = fd_safe_negate(axmax);
        newmax = TaggedZero;
        break;
      case 0xa2: /* 0..+(axmax) * inf..+(aymax) */
      case 0xa3: /* 0..+(axmax) * inf..sup */
      case 0xa6: /* 0..+(axmax) * -(aymin)..+(aymax) */
      case 0xa7: /* 0..+(axmax) * -(aymin)..sup */
        newmin = fd_safe_negate(axmax);
        newmax = axmax;
        break;
      case 0x61: /* -(axmin)..+(axmax) * inf..0 */
      case 0x65: /* -(axmin)..+(axmax) * -(aymin)..0 */
        newmin = fd_safe_negate(axmax);
        newmax = axmin;
        break;
      case 0x21: /* inf..+(axmax) * inf..0 */
      case 0x25: /* inf..+(axmax) * -(aymin)..0 */
        newmin = fd_safe_negate(axmax);
        newmax = Sup;
        break;
      case 0xe5: /* +(axmin)..+(axmax) * -(aymin)..0 */
        newmin = fd_safe_negate(axmax);
        newmax = fd_safe_negate(fd_safe_divd(axmin,aymin));
        break;
      case 0x4b: /* -(axmin)..-(axmax) * 0..sup */
      case 0x5a: /* -(axmin)..0 * 0..+(aymax) */
      case 0x5b: /* -(axmin)..0 * 0..sup */
        newmin = fd_safe_negate(axmin);
        newmax = TaggedZero;
        break;
      case 0x6a: /* -(axmin)..+(axmax) * 0..+(aymax) */
      case 0x6b: /* -(axmin)..+(axmax) * 0..sup */
        newmin = fd_safe_negate(axmin);
        newmax = axmax;
        break;
      case 0x52: /* -(axmin)..0 * inf..+(aymax) */
      case 0x53: /* -(axmin)..0 * inf..sup */
      case 0x56: /* -(axmin)..0 * -(aymin)..+(aymax) */
      case 0x57: /* -(axmin)..0 * -(aymin)..sup */
        newmin = fd_safe_negate(axmin);
        newmax = axmin;
        break;
      case 0x7a: /* -(axmin)..sup * 0..+(aymax) */
      case 0x7b: /* -(axmin)..sup * 0..sup */
        newmin = fd_safe_negate(axmin);
        newmax = Sup;
        break;
      case 0x4a: /* -(axmin)..-(axmax) * 0..+(aymax) */
        newmin = fd_safe_negate(axmin);
        newmax = fd_safe_negate(fd_safe_divd(axmax,aymax));
        break;
      case 0xb: /* inf..-(axmax) * 0..sup */
      case 0xf: /* inf..-(axmax) * +(aymin)..sup */
      case 0x1a: /* inf..0 * 0..+(aymax) */
      case 0x1b: /* inf..0 * 0..sup */
      case 0x1e: /* inf..0 * +(aymin)..+(aymax) */
      case 0x1f: /* inf..0 * +(aymin)..sup */
      case 0xb0: /* 0..sup * inf..-(aymax) */
      case 0xb4: /* 0..sup * -(aymin)..-(aymax) */
      case 0xb1: /* 0..sup * inf..0 */
      case 0xb5: /* 0..sup * -(aymin)..0 */
      case 0xf0: /* +(axmin)..sup * inf..-(aymax) */
      case 0xf1: /* +(axmin)..sup * inf..0 */
        newmin = Inf;
        newmax = TaggedZero;
        break;
      case 0x2a: /* inf..+(axmax) * 0..+(aymax) */
      case 0x2b: /* inf..+(axmax) * 0..sup */
        newmin = Inf;
        newmax = axmax;
        break;
      case 0x71: /* -(axmin)..sup * inf..0 */
      case 0x75: /* -(axmin)..sup * -(aymin)..0 */
        newmin = Inf;
        newmax = axmin;
        break;
      case 0x2e: /* inf..+(axmax) * +(aymin)..+(aymax) */
      case 0x2f: /* inf..+(axmax) * +(aymin)..sup */
        newmin = Inf;
        newmax = fd_safe_divd(axmax,aymin);
        break;
      case 0x70: /* -(axmin)..sup * inf..-(aymax) */
      case 0x74: /* -(axmin)..sup * -(aymin)..-(aymax) */
        newmin = Inf;
        newmax = fd_safe_divd(axmin,aymax);
        break;
      case 0xa: /* inf..-(axmax) * 0..+(aymax) */
      case 0xe: /* inf..-(axmax) * +(aymin)..+(aymax) */
        newmin = Inf;
        newmax = fd_safe_negate(fd_safe_divd(axmax,aymax));
        break;
      case 0xf4: /* +(axmin)..sup * -(aymin)..-(aymax) */
      case 0xf5: /* +(axmin)..sup * -(aymin)..0 */
        newmin = Inf;
        newmax = fd_safe_negate(fd_safe_divd(axmin,aymin));
        break;
      case 0xa0: /* 0..+(axmax) * inf..-(aymax) */
      case 0xa4: /* 0..+(axmax) * -(aymin)..-(aymax) */
      case 0xe0: /* +(axmin)..+(axmax) * inf..-(aymax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,aymax));
        newmax = TaggedZero;
        break;
      case 0x20: /* inf..+(axmax) * inf..-(aymax) */
      case 0x24: /* inf..+(axmax) * -(aymin)..-(aymax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,aymax));
        newmax = Sup;
        break;
      case 0x60: /* -(axmin)..+(axmax) * inf..-(aymax) */
      case 0x64: /* -(axmin)..+(axmax) * -(aymin)..-(aymax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,aymax));
        newmax = fd_safe_divd(axmin,aymax);
        break;
      case 0xe4: /* +(axmin)..+(axmax) * -(aymin)..-(aymax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,aymax));
        newmax = fd_safe_negate(fd_safe_divd(axmin,aymin));
        break;
      case 0x4f: /* -(axmin)..-(axmax) * +(aymin)..sup */
      case 0x5e: /* -(axmin)..0 * +(aymin)..+(aymax) */
      case 0x5f: /* -(axmin)..0 * +(aymin)..sup */
        newmin = fd_safe_negate(fd_safe_divd(axmin,aymin));
        newmax = TaggedZero;
        break;
      case 0x7e: /* -(axmin)..sup * +(aymin)..+(aymax) */
      case 0x7f: /* -(axmin)..sup * +(aymin)..sup */
        newmin = fd_safe_negate(fd_safe_divd(axmin,aymin));
        newmax = Sup;
        break;
      case 0x6e: /* -(axmin)..+(axmax) * +(aymin)..+(aymax) */
      case 0x6f: /* -(axmin)..+(axmax) * +(aymin)..sup */
        newmin = fd_safe_negate(fd_safe_divd(axmin,aymin));
        newmax = fd_safe_divd(axmax,aymin);
        break;
      case 0x4e: /* -(axmin)..-(axmax) * +(aymin)..+(aymax) */
        newmin = fd_safe_negate(fd_safe_divd(axmin,aymin));
        newmax = fd_safe_negate(fd_safe_divd(axmax,aymax));
        break;
      case 0x62: /* -(axmin)..+(axmax) * inf..+(aymax) */
      case 0x63: /* -(axmin)..+(axmax) * inf..sup */
      case 0x66: /* -(axmin)..+(axmax) * -(aymin)..+(aymax) */
      case 0x67: /* -(axmin)..+(axmax) * -(aymin)..sup */
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      case 0x3: /* inf..-(axmax) * inf..sup */
      case 0xf3: /* +(axmin)..sup * inf..sup */
        newmin = fd_safe_plus(TaggedZero,MakeSmall(1));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x7: /* inf..-(axmax) * -(aymin)..sup */
        newmin = fd_safe_plus(TaggedZero,MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmax,aymin),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xf2: /* +(axmin)..sup * inf..+(aymax) */
        newmin = fd_safe_plus(TaggedZero,MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmin,aymax),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x2: /* inf..-(axmax) * inf..+(aymax) */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmax,aymax)),MakeSmall(1));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x6: /* inf..-(axmax) * -(aymin)..+(aymax) */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmax,aymax)),MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmax,aymin),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xf7: /* +(axmin)..sup * -(aymin)..sup */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmin,aymin)),MakeSmall(1));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xf6: /* +(axmin)..sup * -(aymin)..+(aymax) */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmin,aymin)),MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmin,aymax),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x43: /* -(axmin)..-(axmax) * inf..sup */
      case 0xe3: /* +(axmin)..+(axmax) * inf..sup */
        newmin = fd_safe_plus(TaggedZero,MakeSmall(1));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      case 0x47: /* -(axmin)..-(axmax) * -(aymin)..sup */
        newmin = fd_safe_plus(TaggedZero,MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmax,aymin),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      case 0xe2: /* +(axmin)..+(axmax) * inf..+(aymax) */
        newmin = fd_safe_plus(TaggedZero,MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmin,aymax),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      case 0x42: /* -(axmin)..-(axmax) * inf..+(aymax) */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmax,aymax)),MakeSmall(1));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      case 0x46: /* -(axmin)..-(axmax) * -(aymin)..+(aymax) */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmax,aymax)),MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmax,aymin),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      case 0xe7: /* +(axmin)..+(axmax) * -(aymin)..sup */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmin,aymin)),MakeSmall(1));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      case 0xe6: /* +(axmin)..+(axmax) * -(aymin)..+(aymax) */
        newmin = fd_safe_plus(fd_safe_negate(fd_safe_divd(axmin,aymin)),MakeSmall(1));
        newmax = fd_safe_minus(fd_safe_divd(axmin,aymax),MakeSmall(1));
        if (dvar_prune_interval_t(dvz, newmin, newmax,w)<0)
          goto ret;
        newmax = fd_safe_max(axmin,axmax);
        newmin = fd_safe_negate(newmax);
        break;
      }
      if (dvar_fix_interval_t(dvz, newmin, newmax)<0) {
	if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	  fd.fd_overflow = TRUE;
	goto ret;
      }
      break;
    case 1:			/* (X,Z) => Y */
      axmin = (Tgez(xmin) ? xmin : fd_safe_negate_val(xmin));
      axmax = (Tgez(xmax) ? xmax : fd_safe_negate_val(xmax));
      azmin = (Tgez(zmin) ? zmin : fd_safe_negate_val(zmin));
      azmax = (Tgez(zmax) ? zmax : fd_safe_negate_val(zmax));
      switch (ARITH_DISPATCH(xmin,xmax,zmin,zmax)) {
      case 0x90: /* 0..0 * inf..-(azmax) */
      case 0x94: /* 0..0 * -(azmin)..-(azmax) */
      case 0x9e: /* 0..0 * +(azmin)..+(azmax) */
      case 0x9f: /* 0..0 * +(azmin)..sup */
        goto ret;
      case 0x12: /* inf..0 * inf..+(azmax) */
      case 0x13: /* inf..0 * inf..sup */
      case 0x16: /* inf..0 * -(azmin)..+(azmax) */
      case 0x17: /* inf..0 * -(azmin)..sup */
      case 0x52: /* -(axmin)..0 * inf..+(azmax) */
      case 0x53: /* -(axmin)..0 * inf..sup */
      case 0x56: /* -(axmin)..0 * -(azmin)..+(azmax) */
      case 0x57: /* -(axmin)..0 * -(azmin)..sup */
      case 0x11: /* inf..0 * inf..0 */
      case 0x15: /* inf..0 * -(azmin)..0 */
      case 0x51: /* -(axmin)..0 * inf..0 */
      case 0x55: /* -(axmin)..0 * -(azmin)..0 */
      case 0x19: /* inf..0 * 0..0 */
      case 0x59: /* -(axmin)..0 * 0..0 */
      case 0x1a: /* inf..0 * 0..+(azmax) */
      case 0x1b: /* inf..0 * 0..sup */
      case 0x5a: /* -(axmin)..0 * 0..+(azmax) */
      case 0x5b: /* -(axmin)..0 * 0..sup */
      case 0x30: /* inf..sup * inf..-(azmax) */
      case 0x34: /* inf..sup * -(azmin)..-(azmax) */
      case 0x22: /* inf..+(axmax) * inf..+(azmax) */
      case 0x23: /* inf..+(axmax) * inf..sup */
      case 0x26: /* inf..+(axmax) * -(azmin)..+(azmax) */
      case 0x27: /* inf..+(axmax) * -(azmin)..sup */
      case 0x32: /* inf..sup * inf..+(azmax) */
      case 0x33: /* inf..sup * inf..sup */
      case 0x36: /* inf..sup * -(azmin)..+(azmax) */
      case 0x37: /* inf..sup * -(azmin)..sup */
      case 0x62: /* -(axmin)..+(axmax) * inf..+(azmax) */
      case 0x63: /* -(axmin)..+(axmax) * inf..sup */
      case 0x66: /* -(axmin)..+(axmax) * -(azmin)..+(azmax) */
      case 0x67: /* -(axmin)..+(axmax) * -(azmin)..sup */
      case 0x72: /* -(axmin)..sup * inf..+(azmax) */
      case 0x73: /* -(axmin)..sup * inf..sup */
      case 0x76: /* -(axmin)..sup * -(azmin)..+(azmax) */
      case 0x77: /* -(axmin)..sup * -(azmin)..sup */
      case 0x21: /* inf..+(axmax) * inf..0 */
      case 0x25: /* inf..+(axmax) * -(azmin)..0 */
      case 0x31: /* inf..sup * inf..0 */
      case 0x35: /* inf..sup * -(azmin)..0 */
      case 0x61: /* -(axmin)..+(axmax) * inf..0 */
      case 0x65: /* -(axmin)..+(axmax) * -(azmin)..0 */
      case 0x71: /* -(axmin)..sup * inf..0 */
      case 0x75: /* -(axmin)..sup * -(azmin)..0 */
      case 0x29: /* inf..+(axmax) * 0..0 */
      case 0x39: /* inf..sup * 0..0 */
      case 0x69: /* -(axmin)..+(axmax) * 0..0 */
      case 0x79: /* -(axmin)..sup * 0..0 */
      case 0x2a: /* inf..+(axmax) * 0..+(azmax) */
      case 0x2b: /* inf..+(axmax) * 0..sup */
      case 0x3a: /* inf..sup * 0..+(azmax) */
      case 0x3b: /* inf..sup * 0..sup */
      case 0x6a: /* -(axmin)..+(axmax) * 0..+(azmax) */
      case 0x6b: /* -(axmin)..+(axmax) * 0..sup */
      case 0x7a: /* -(axmin)..sup * 0..+(azmax) */
      case 0x7b: /* -(axmin)..sup * 0..sup */
      case 0x3e: /* inf..sup * +(azmin)..+(azmax) */
      case 0x3f: /* inf..sup * +(azmin)..sup */
      case 0x92: /* 0..0 * inf..+(azmax) */
      case 0x93: /* 0..0 * inf..sup */
      case 0x96: /* 0..0 * -(azmin)..+(azmax) */
      case 0x97: /* 0..0 * -(azmin)..sup */
      case 0x91: /* 0..0 * inf..0 */
      case 0x95: /* 0..0 * -(azmin)..0 */
      case 0x99: /* 0..0 * 0..0 */
      case 0x9a: /* 0..0 * 0..+(azmax) */
      case 0x9b: /* 0..0 * 0..sup */
      case 0xa2: /* 0..+(axmax) * inf..+(azmax) */
      case 0xa3: /* 0..+(axmax) * inf..sup */
      case 0xa6: /* 0..+(axmax) * -(azmin)..+(azmax) */
      case 0xa7: /* 0..+(axmax) * -(azmin)..sup */
      case 0xb2: /* 0..sup * inf..+(azmax) */
      case 0xb3: /* 0..sup * inf..sup */
      case 0xb6: /* 0..sup * -(azmin)..+(azmax) */
      case 0xb7: /* 0..sup * -(azmin)..sup */
      case 0xa1: /* 0..+(axmax) * inf..0 */
      case 0xa5: /* 0..+(axmax) * -(azmin)..0 */
      case 0xb1: /* 0..sup * inf..0 */
      case 0xb5: /* 0..sup * -(azmin)..0 */
      case 0xa9: /* 0..+(axmax) * 0..0 */
      case 0xb9: /* 0..sup * 0..0 */
      case 0xaa: /* 0..+(axmax) * 0..+(azmax) */
      case 0xab: /* 0..+(axmax) * 0..sup */
      case 0xba: /* 0..sup * 0..+(azmax) */
      case 0xbb: /* 0..sup * 0..sup */
      default:
        continue;
      case 0x3: /* inf..-(axmax) * inf..sup */
      case 0x43: /* -(axmin)..-(axmax) * inf..sup */
      case 0xe3: /* +(axmin)..+(axmax) * inf..sup */
      case 0xf3: /* +(axmin)..sup * inf..sup */
        newmin = MakeSmall(1);
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xe1: /* +(axmin)..+(axmax) * inf..0 */
      case 0xf1: /* +(axmin)..sup * inf..0 */
        newmin = MakeSmall(1);
        newmax = axmin;
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xb: /* inf..-(axmax) * 0..sup */
      case 0x4b: /* -(axmin)..-(axmax) * 0..sup */
        newmin = MakeSmall(1);
        newmax = axmax;
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x7: /* inf..-(axmax) * -(azmin)..sup */
      case 0x47: /* -(axmin)..-(axmax) * -(azmin)..sup */
        newmin = MakeSmall(1);
        newmax = fd_safe_minus(fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))),MakeSmall(1));
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xe2: /* +(axmin)..+(axmax) * inf..+(azmax) */
      case 0xf2: /* +(axmin)..sup * inf..+(azmax) */
        newmin = MakeSmall(1);
        newmax = fd_safe_minus(fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))),MakeSmall(1));
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x1: /* inf..-(axmax) * inf..0 */
      case 0x41: /* -(axmin)..-(axmax) * inf..0 */
        newmin = fd_safe_negate(axmax);
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x9: /* inf..-(axmax) * 0..0 */
      case 0x49: /* -(axmin)..-(axmax) * 0..0 */
        newmin = fd_safe_negate(axmax);
        newmax = axmax;
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x5: /* inf..-(axmax) * -(azmin)..0 */
      case 0x45: /* -(axmin)..-(axmax) * -(azmin)..0 */
        newmin = fd_safe_negate(axmax);
        newmax = fd_safe_minus(fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))),MakeSmall(1));
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xeb: /* +(axmin)..+(axmax) * 0..sup */
      case 0xfb: /* +(axmin)..sup * 0..sup */
        newmin = fd_safe_negate(axmin);
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xe9: /* +(axmin)..+(axmax) * 0..0 */
      case 0xf9: /* +(axmin)..sup * 0..0 */
        newmin = fd_safe_negate(axmin);
        newmax = axmin;
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xea: /* +(axmin)..+(axmax) * 0..+(azmax) */
      case 0xfa: /* +(axmin)..sup * 0..+(azmax) */
        newmin = fd_safe_negate(axmin);
        newmax = fd_safe_minus(fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))),MakeSmall(1));
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x2: /* inf..-(axmax) * inf..+(azmax) */
      case 0x42: /* -(axmin)..-(axmax) * inf..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xa: /* inf..-(axmax) * 0..+(azmax) */
      case 0x4a: /* -(axmin)..-(axmax) * 0..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))));
        newmax = axmax;
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x6: /* inf..-(axmax) * -(azmin)..+(azmax) */
      case 0x46: /* -(axmin)..-(axmax) * -(azmin)..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))));
        newmax = fd_safe_minus(fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))),MakeSmall(1));
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xe7: /* +(axmin)..+(axmax) * -(azmin)..sup */
      case 0xf7: /* +(axmin)..sup * -(azmin)..sup */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))));
        newmax = MakeSmall(-1);
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xe5: /* +(axmin)..+(axmax) * -(azmin)..0 */
      case 0xf5: /* +(axmin)..sup * -(azmin)..0 */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))));
        newmax = axmin;
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0xe6: /* +(axmin)..+(axmax) * -(azmin)..+(azmax) */
      case 0xf6: /* +(axmin)..sup * -(azmin)..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))));
        newmax = fd_safe_minus(fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))),MakeSmall(1));
        if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x0: /* inf..-(axmax) * inf..-(azmax) */
      case 0x10: /* inf..0 * inf..-(azmax) */
      case 0x14: /* inf..0 * -(azmin)..-(azmax) */
      case 0xbe: /* 0..sup * +(azmin)..+(azmax) */
      case 0xbf: /* 0..sup * +(azmin)..sup */
      case 0xff: /* +(axmin)..sup * +(azmin)..sup */
        newmin = TaggedZero;
        newmax = Sup;
        break;
      case 0xae: /* 0..+(axmax) * +(azmin)..+(azmax) */
      case 0xaf: /* 0..+(axmax) * +(azmin)..sup */
      case 0xef: /* +(axmin)..+(axmax) * +(azmin)..sup */
        newmin = TaggedZero;
        newmax = fd_safe_divd(axmax,azmin);
        break;
      case 0x40: /* -(axmin)..-(axmax) * inf..-(azmax) */
      case 0x50: /* -(axmin)..0 * inf..-(azmax) */
      case 0x54: /* -(axmin)..0 * -(azmin)..-(azmax) */
        newmin = TaggedZero;
        newmax = fd_safe_divd(axmin,azmax);
        break;
      case 0x4: /* inf..-(axmax) * -(azmin)..-(azmax) */
        newmin = fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1)));
        newmax = Sup;
        break;
      case 0x44: /* -(axmin)..-(axmax) * -(azmin)..-(azmax) */
        newmin = fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1)));
        newmax = fd_safe_divd(axmin,azmax);
        break;
      case 0xfe: /* +(axmin)..sup * +(azmin)..+(azmax) */
        newmin = fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1)));
        newmax = Sup;
        break;
      case 0xee: /* +(axmin)..+(axmax) * +(azmin)..+(azmax) */
        newmin = fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1)));
        newmax = fd_safe_divd(axmax,azmin);
        break;
      case 0xf: /* inf..-(axmax) * +(azmin)..sup */
      case 0x1e: /* inf..0 * +(azmin)..+(azmax) */
      case 0x1f: /* inf..0 * +(azmin)..sup */
      case 0xb0: /* 0..sup * inf..-(azmax) */
      case 0xb4: /* 0..sup * -(azmin)..-(azmax) */
      case 0xf0: /* +(axmin)..sup * inf..-(azmax) */
        newmin = Inf;
        newmax = TaggedZero;
        break;
      case 0x2e: /* inf..+(axmax) * +(azmin)..+(azmax) */
      case 0x2f: /* inf..+(axmax) * +(azmin)..sup */
        newmin = Inf;
        newmax = fd_safe_divd(axmax,azmin);
        break;
      case 0x70: /* -(axmin)..sup * inf..-(azmax) */
      case 0x74: /* -(axmin)..sup * -(azmin)..-(azmax) */
        newmin = Inf;
        newmax = fd_safe_divd(axmin,azmax);
        break;
      case 0xe: /* inf..-(axmax) * +(azmin)..+(azmax) */
        newmin = Inf;
        newmax = fd_safe_negate(fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))));
        break;
      case 0xf4: /* +(axmin)..sup * -(azmin)..-(azmax) */
        newmin = Inf;
        newmax = fd_safe_negate(fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))));
        break;
      case 0xa0: /* 0..+(axmax) * inf..-(azmax) */
      case 0xa4: /* 0..+(axmax) * -(azmin)..-(azmax) */
      case 0xe0: /* +(axmin)..+(axmax) * inf..-(azmax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,azmax));
        newmax = TaggedZero;
        break;
      case 0x20: /* inf..+(axmax) * inf..-(azmax) */
      case 0x24: /* inf..+(axmax) * -(azmin)..-(azmax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,azmax));
        newmax = Sup;
        break;
      case 0x60: /* -(axmin)..+(axmax) * inf..-(azmax) */
      case 0x64: /* -(axmin)..+(axmax) * -(azmin)..-(azmax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,azmax));
        newmax = fd_safe_divd(axmin,azmax);
        break;
      case 0xe4: /* +(axmin)..+(axmax) * -(azmin)..-(azmax) */
        newmin = fd_safe_negate(fd_safe_divd(axmax,azmax));
        newmax = fd_safe_negate(fd_safe_divu(fd_safe_plus(axmin,MakeSmall(1)),fd_safe_plus(azmin,MakeSmall(1))));
        break;
      case 0x4f: /* -(axmin)..-(axmax) * +(azmin)..sup */
      case 0x5e: /* -(axmin)..0 * +(azmin)..+(azmax) */
      case 0x5f: /* -(axmin)..0 * +(azmin)..sup */
        newmin = fd_safe_negate(fd_safe_divd(axmin,azmin));
        newmax = TaggedZero;
        break;
      case 0x7e: /* -(axmin)..sup * +(azmin)..+(azmax) */
      case 0x7f: /* -(axmin)..sup * +(azmin)..sup */
        newmin = fd_safe_negate(fd_safe_divd(axmin,azmin));
        newmax = Sup;
        break;
      case 0x6e: /* -(axmin)..+(axmax) * +(azmin)..+(azmax) */
      case 0x6f: /* -(axmin)..+(axmax) * +(azmin)..sup */
        newmin = fd_safe_negate(fd_safe_divd(axmin,azmin));
        newmax = fd_safe_divd(axmax,azmin);
        break;
      case 0x4e: /* -(axmin)..-(axmax) * +(azmin)..+(azmax) */
        newmin = fd_safe_negate(fd_safe_divd(axmin,azmin));
        newmax = fd_safe_negate(fd_safe_divu(fd_safe_plus(axmax,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))));
        break;
      }
      if (dvar_fix_interval_t(dvy, newmin, newmax)<0) {
	if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	  fd.fd_overflow = TRUE;
	goto ret;
      }
      break;
    case 2:			/* (Y,Z) => X */
      aymin = (Tgez(ymin) ? ymin : fd_safe_negate_val(ymin));
      aymax = (Tgez(ymax) ? ymax : fd_safe_negate_val(ymax));
      azmin = (Tgez(zmin) ? zmin : fd_safe_negate_val(zmin));
      azmax = (Tgez(zmax) ? zmax : fd_safe_negate_val(zmax));
      switch (ARITH_DISPATCH(ymin,ymax,zmin,zmax)) {
        /* AUTOMATICALLY GENERATED CASES FOR div PRUNING DVAR dvx */
      case 0x90: /* 0..0 * inf..-(azmax) */
      case 0x94: /* 0..0 * -(azmin)..-(azmax) */
      case 0x91: /* 0..0 * inf..0 */
      case 0x95: /* 0..0 * -(azmin)..0 */
      case 0x92: /* 0..0 * inf..+(azmax) */
      case 0x93: /* 0..0 * inf..sup */
      case 0x96: /* 0..0 * -(azmin)..+(azmax) */
      case 0x97: /* 0..0 * -(azmin)..sup */
      case 0x99: /* 0..0 * 0..0 */
      case 0x9a: /* 0..0 * 0..+(azmax) */
      case 0x9b: /* 0..0 * 0..sup */
      case 0x9e: /* 0..0 * +(azmin)..+(azmax) */
      case 0x9f: /* 0..0 * +(azmin)..sup */
        goto ret;
      case 0x1: /* inf..-(aymax) * inf..0 */
      case 0x5: /* inf..-(aymax) * -(azmin)..0 */
      case 0x2: /* inf..-(aymax) * inf..+(azmax) */
      case 0x3: /* inf..-(aymax) * inf..sup */
      case 0x6: /* inf..-(aymax) * -(azmin)..+(azmax) */
      case 0x7: /* inf..-(aymax) * -(azmin)..sup */
      case 0x43: /* -(aymin)..-(aymax) * inf..sup */
      case 0x9: /* inf..-(aymax) * 0..0 */
      case 0xa: /* inf..-(aymax) * 0..+(azmax) */
      case 0xb: /* inf..-(aymax) * 0..sup */
      case 0x11: /* inf..0 * inf..0 */
      case 0x15: /* inf..0 * -(azmin)..0 */
      case 0x12: /* inf..0 * inf..+(azmax) */
      case 0x13: /* inf..0 * inf..sup */
      case 0x16: /* inf..0 * -(azmin)..+(azmax) */
      case 0x17: /* inf..0 * -(azmin)..sup */
      case 0x53: /* -(aymin)..0 * inf..sup */
      case 0x19: /* inf..0 * 0..0 */
      case 0x1a: /* inf..0 * 0..+(azmax) */
      case 0x1b: /* inf..0 * 0..sup */
      case 0x21: /* inf..+(aymax) * inf..0 */
      case 0x25: /* inf..+(aymax) * -(azmin)..0 */
      case 0x31: /* inf..sup * inf..0 */
      case 0x35: /* inf..sup * -(azmin)..0 */
      case 0x61: /* -(aymin)..+(aymax) * inf..0 */
      case 0x71: /* -(aymin)..sup * inf..0 */
      case 0x75: /* -(aymin)..sup * -(azmin)..0 */
      case 0x22: /* inf..+(aymax) * inf..+(azmax) */
      case 0x23: /* inf..+(aymax) * inf..sup */
      case 0x26: /* inf..+(aymax) * -(azmin)..+(azmax) */
      case 0x27: /* inf..+(aymax) * -(azmin)..sup */
      case 0x32: /* inf..sup * inf..+(azmax) */
      case 0x33: /* inf..sup * inf..sup */
      case 0x36: /* inf..sup * -(azmin)..+(azmax) */
      case 0x37: /* inf..sup * -(azmin)..sup */
      case 0x62: /* -(aymin)..+(aymax) * inf..+(azmax) */
      case 0x63: /* -(aymin)..+(aymax) * inf..sup */
      case 0x67: /* -(aymin)..+(aymax) * -(azmin)..sup */
      case 0x72: /* -(aymin)..sup * inf..+(azmax) */
      case 0x73: /* -(aymin)..sup * inf..sup */
      case 0x76: /* -(aymin)..sup * -(azmin)..+(azmax) */
      case 0x77: /* -(aymin)..sup * -(azmin)..sup */
      case 0x29: /* inf..+(aymax) * 0..0 */
      case 0x39: /* inf..sup * 0..0 */
      case 0x79: /* -(aymin)..sup * 0..0 */
      case 0x2a: /* inf..+(aymax) * 0..+(azmax) */
      case 0x2b: /* inf..+(aymax) * 0..sup */
      case 0x3a: /* inf..sup * 0..+(azmax) */
      case 0x3b: /* inf..sup * 0..sup */
      case 0x6b: /* -(aymin)..+(aymax) * 0..sup */
      case 0x7a: /* -(aymin)..sup * 0..+(azmax) */
      case 0x7b: /* -(aymin)..sup * 0..sup */
      case 0xb1: /* 0..sup * inf..0 */
      case 0xb5: /* 0..sup * -(azmin)..0 */
      case 0xa3: /* 0..+(aymax) * inf..sup */
      case 0xb2: /* 0..sup * inf..+(azmax) */
      case 0xb3: /* 0..sup * inf..sup */
      case 0xb6: /* 0..sup * -(azmin)..+(azmax) */
      case 0xb7: /* 0..sup * -(azmin)..sup */
      case 0xb9: /* 0..sup * 0..0 */
      case 0xba: /* 0..sup * 0..+(azmax) */
      case 0xbb: /* 0..sup * 0..sup */
      case 0xf1: /* +(aymin)..sup * inf..0 */
      case 0xf5: /* +(aymin)..sup * -(azmin)..0 */
      case 0xe3: /* +(aymin)..+(aymax) * inf..sup */
      case 0xf2: /* +(aymin)..sup * inf..+(azmax) */
      case 0xf3: /* +(aymin)..sup * inf..sup */
      case 0xf6: /* +(aymin)..sup * -(azmin)..+(azmax) */
      case 0xf7: /* +(aymin)..sup * -(azmin)..sup */
      case 0xf9: /* +(aymin)..sup * 0..0 */
      case 0xfa: /* +(aymin)..sup * 0..+(azmax) */
      case 0xfb: /* +(aymin)..sup * 0..sup */
      default:
        continue;
      case 0x10: /* inf..0 * inf..-(azmax) */
      case 0x14: /* inf..0 * -(azmin)..-(azmax) */
      case 0x50: /* -(aymin)..0 * inf..-(azmax) */
        newmin = azmax;
        newmax = Sup;
        break;
      case 0x54: /* -(aymin)..0 * -(azmin)..-(azmax) */
        newmin = azmax;
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1));
        break;
      case 0xaf: /* 0..+(aymax) * +(azmin)..sup */
      case 0xbe: /* 0..sup * +(azmin)..+(azmax) */
      case 0xbf: /* 0..sup * +(azmin)..sup */
        newmin = azmin;
        newmax = Sup;
        break;
      case 0xae: /* 0..+(aymax) * +(azmin)..+(azmax) */
        newmin = azmin;
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1));
        break;
      case 0x0: /* inf..-(aymax) * inf..-(azmax) */
      case 0x4: /* inf..-(aymax) * -(azmin)..-(azmax) */
      case 0x40: /* -(aymin)..-(aymax) * inf..-(azmax) */
        newmin = fd_safe_mul(aymax,azmax);
        newmax = Sup;
        break;
      case 0x44: /* -(aymin)..-(aymax) * -(azmin)..-(azmax) */
        newmin = fd_safe_mul(aymax,azmax);
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1));
        break;
      case 0xef: /* +(aymin)..+(aymax) * +(azmin)..sup */
      case 0xfe: /* +(aymin)..sup * +(azmin)..+(azmax) */
      case 0xff: /* +(aymin)..sup * +(azmin)..sup */
        newmin = fd_safe_mul(aymin,azmin);
        newmax = Sup;
        break;
      case 0xee: /* +(aymin)..+(aymax) * +(azmin)..+(azmax) */
        newmin = fd_safe_mul(aymin,azmin);
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1));
        break;
      case 0xab: /* 0..+(aymax) * 0..sup */
      case 0xeb: /* +(aymin)..+(aymax) * 0..sup */
        newmin = fd_safe_minus(MakeSmall(1),aymax);
        newmax = Sup;
        break;
      case 0xa9: /* 0..+(aymax) * 0..0 */
      case 0xe9: /* +(aymin)..+(aymax) * 0..0 */
        newmax = fd_safe_minus(aymax,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        break;
      case 0xaa: /* 0..+(aymax) * 0..+(azmax) */
      case 0xea: /* +(aymin)..+(aymax) * 0..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),aymax);
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1));
        break;
      case 0x41: /* -(aymin)..-(aymax) * inf..0 */
      case 0x51: /* -(aymin)..0 * inf..0 */
        newmin = fd_safe_minus(MakeSmall(1),aymin);
        newmax = Sup;
        break;
      case 0x49: /* -(aymin)..-(aymax) * 0..0 */
      case 0x59: /* -(aymin)..0 * 0..0 */
        newmax = fd_safe_minus(aymin,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        break;
      case 0x45: /* -(aymin)..-(aymax) * -(azmin)..0 */
      case 0x55: /* -(aymin)..0 * -(azmin)..0 */
        newmin = fd_safe_minus(MakeSmall(1),aymin);
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1));
        break;
      case 0xa7: /* 0..+(aymax) * -(azmin)..sup */
      case 0xe7: /* +(aymin)..+(aymax) * -(azmin)..sup */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymax,azmin),aymax));
        newmax = Sup;
        break;
      case 0xa5: /* 0..+(aymax) * -(azmin)..0 */
      case 0xe5: /* +(aymin)..+(aymax) * -(azmin)..0 */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymax,azmin),aymax));
        newmax = fd_safe_minus(aymax,MakeSmall(1));
        break;
      case 0xa6: /* 0..+(aymax) * -(azmin)..+(azmax) */
      case 0xe6: /* +(aymin)..+(aymax) * -(azmin)..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymax,azmin),aymax));
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1));
        break;
      case 0xa4: /* 0..+(aymax) * -(azmin)..-(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymax,azmin),aymax));
        newmax = fd_safe_negate(azmax);
        break;
      case 0xe4: /* +(aymin)..+(aymax) * -(azmin)..-(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymax,azmin),aymax));
        newmax = fd_safe_negate(fd_safe_mul(aymin,azmax));
        break;
      case 0x42: /* -(aymin)..-(aymax) * inf..+(azmax) */
      case 0x52: /* -(aymin)..0 * inf..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymin,azmax),aymin));
        newmax = Sup;
        break;
      case 0x4a: /* -(aymin)..-(aymax) * 0..+(azmax) */
      case 0x5a: /* -(aymin)..0 * 0..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymin,azmax),aymin));
        newmax = fd_safe_minus(aymin,MakeSmall(1));
        break;
      case 0x46: /* -(aymin)..-(aymax) * -(azmin)..+(azmax) */
      case 0x56: /* -(aymin)..0 * -(azmin)..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymin,azmax),aymin));
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1));
        break;
      case 0x5e: /* -(aymin)..0 * +(azmin)..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymin,azmax),aymin));
        newmax = fd_safe_negate(azmin);
        break;
      case 0x4e: /* -(aymin)..-(aymax) * +(azmin)..+(azmax) */
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymin,azmax),aymin));
        newmax = fd_safe_negate(fd_safe_mul(aymax,azmin));
        break;
      case 0xa1: /* 0..+(aymax) * inf..0 */
      case 0xe1: /* +(aymin)..+(aymax) * inf..0 */
        newmin = Inf;
        newmax = fd_safe_minus(aymax,MakeSmall(1));
        break;
      case 0x4b: /* -(aymin)..-(aymax) * 0..sup */
      case 0x5b: /* -(aymin)..0 * 0..sup */
        newmin = Inf;
        newmax = fd_safe_minus(aymin,MakeSmall(1));
        break;
      case 0xa2: /* 0..+(aymax) * inf..+(azmax) */
      case 0xe2: /* +(aymin)..+(aymax) * inf..+(azmax) */
        newmin = Inf;
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1));
        break;
      case 0x47: /* -(aymin)..-(aymax) * -(azmin)..sup */
      case 0x57: /* -(aymin)..0 * -(azmin)..sup */
        newmin = Inf;
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1));
        break;
      case 0xa0: /* 0..+(aymax) * inf..-(azmax) */
      case 0xb0: /* 0..sup * inf..-(azmax) */
      case 0xb4: /* 0..sup * -(azmin)..-(azmax) */
        newmin = Inf;
        newmax = fd_safe_negate(azmax);
        break;
      case 0x1e: /* inf..0 * +(azmin)..+(azmax) */
      case 0x1f: /* inf..0 * +(azmin)..sup */
      case 0x5f: /* -(aymin)..0 * +(azmin)..sup */
        newmin = Inf;
        newmax = fd_safe_negate(azmin);
        break;
      case 0xe: /* inf..-(aymax) * +(azmin)..+(azmax) */
      case 0xf: /* inf..-(aymax) * +(azmin)..sup */
      case 0x4f: /* -(aymin)..-(aymax) * +(azmin)..sup */
        newmin = Inf;
        newmax = fd_safe_negate(fd_safe_mul(aymax,azmin));
        break;
      case 0xe0: /* +(aymin)..+(aymax) * inf..-(azmax) */
      case 0xf0: /* +(aymin)..sup * inf..-(azmax) */
      case 0xf4: /* +(aymin)..sup * -(azmin)..-(azmax) */
        newmin = Inf;
        newmax = fd_safe_negate(fd_safe_mul(aymin,azmax));
        break;
      case 0x6a: /* -(aymin)..+(aymax) * 0..+(azmax) */
        newmin = fd_safe_negate(fd_safe_max(fd_safe_minus(aymax,MakeSmall(1)),fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmax),aymin),MakeSmall(1))));
        newmax = fd_safe_max(fd_safe_minus(aymin,MakeSmall(1)),fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1)));
        break;
      case 0x69: /* -(aymin)..+(aymax) * 0..0 */
        newmax = fd_safe_max(fd_safe_minus(aymin,MakeSmall(1)),fd_safe_minus(aymax,MakeSmall(1)));
        newmin = fd_safe_negate(newmax);
        break;
      case 0x65: /* -(aymin)..+(aymax) * -(azmin)..0 */
        newmin = fd_safe_negate(fd_safe_max(fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmin),aymax),MakeSmall(1)),fd_safe_minus(aymin,MakeSmall(1))));
        newmax = fd_safe_max(fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1)),fd_safe_minus(aymax,MakeSmall(1)));
        break;
      case 0x66: /* -(aymin)..+(aymax) * -(azmin)..+(azmax) */
        newmin = fd_safe_negate(fd_safe_max(fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmin),aymax),MakeSmall(1)),fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmax),aymin),MakeSmall(1))));
        newmax = fd_safe_max(fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1)),fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1)));
        break;
      case 0x20: /* inf..+(aymax) * inf..-(azmax) */
      case 0x30: /* inf..sup * inf..-(azmax) */
      case 0x34: /* inf..sup * -(azmin)..-(azmax) */
      case 0x60: /* -(aymin)..+(aymax) * inf..-(azmax) */
      case 0x70: /* -(aymin)..sup * inf..-(azmax) */
        newmax = fd_safe_minus(azmax,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x2f: /* inf..+(aymax) * +(azmin)..sup */
      case 0x3e: /* inf..sup * +(azmin)..+(azmax) */
      case 0x3f: /* inf..sup * +(azmin)..sup */
      case 0x6f: /* -(aymin)..+(aymax) * +(azmin)..sup */
      case 0x7f: /* -(aymin)..sup * +(azmin)..sup */
        newmax = fd_safe_minus(azmin,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        continue;
      case 0x24: /* inf..+(aymax) * -(azmin)..-(azmax) */
        newmax = fd_safe_minus(azmax,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymax,azmin),aymax));
        newmax = Sup;
        break;
      case 0x64: /* -(aymin)..+(aymax) * -(azmin)..-(azmax) */
        newmax = fd_safe_minus(azmax,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymax,azmin),aymax));
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1));
        break;
      case 0x7e: /* -(aymin)..sup * +(azmin)..+(azmax) */
        newmax = fd_safe_minus(azmin,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymin,azmax),aymin));
        newmax = Sup;
        break;
      case 0x6e: /* -(aymin)..+(aymax) * +(azmin)..+(azmax) */
        newmax = fd_safe_minus(azmin,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(fd_safe_mul(aymin,azmax),aymin));
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1));
        break;
      case 0x2e: /* inf..+(aymax) * +(azmin)..+(azmax) */
        newmax = fd_safe_minus(azmin,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        newmin = Inf;
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymax,azmax),aymax),MakeSmall(1));
        break;
      case 0x74: /* -(aymin)..sup * -(azmin)..-(azmax) */
        newmax = fd_safe_minus(azmax,MakeSmall(1));
        newmin = fd_safe_negate(newmax);
        if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
          goto ret;
        newmin = Inf;
        newmax = fd_safe_minus(fd_safe_plus(fd_safe_mul(aymin,azmin),aymin),MakeSmall(1));
        break;
      }
      if (dvar_fix_interval_t(dvx, newmin, newmax)<0) {
	if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	  fd.fd_overflow = TRUE;
	goto ret;
      }
      break;
    }
  }
#if 0
  /* shaving */
  if (!shave_bounds(w,dvx,0))
    goto ret;
#endif
  if (dvar_is_integer(dvx) && dvar_is_integer(dvy) && dvar_is_integer(dvz)) {
    ent = dvar_min_l(dvx)/dvar_min_l(dvy)==dvar_min_l(dvz) ? 1 : -1;
  } else {
    ent = 0;
  }
  for (i=0; i<3; i++)
    dvar_pruning_done(w,dvx+i);
  for (i=0; i<3; i++)
    dvar_export(w,dvx+i);
 ret:
  if (ent==1)
    Pfree;
  dvar_export_done(w,Actions, ent);
}


/*
  '$fd_modulo'(State0, State, Actions).
  State = state(X-XMut, Y-YMut, Z-ZMut, B-Bmut)
  Z #= X mod Y AND (Y=0 implies B=0)
*/
void SPCDECL
prolog_fd_modulo MAGIC (HIDDEN_PROTO
			SP_term_ref State,
			SP_term_ref NewState,
			SP_term_ref Actions)
{
  WAMENV;
  Dvar dvx, dvy, dvz;
  TAGGED newmin, newmax, axmin, axmax, aymin, aymax, azmin, azmax;
  int i, iter;
  TAGGED handle, t1;
  SP_BOOL committed;
  struct arith_data *pdata;
  int ent = -1;			/* disentailed unless otherwise */

  (void)State;                 /* [PM] 3.9b5 avoid -Wunused */
/*    X(0) = RefTerm(State0); */
  w->numstack_end = NULL;
  dvar_export_start(w);
  RefTerm(NewState) = fd_static_output_state(w,&handle,&committed);
  if (!IsVar(handle)) {		/* got [Flag | '$free'(Ptr)] */
    pdata = Pdata(struct arith_data,handle);
  } else {			/* build persistent state */
    pdata = Palloc(struct arith_data, 4*sizeof(struct dvar), handle);
    pdata->destructor = arith_destructor;
    pdata->nrefs = 6;
    FD_STORE_SPENV(pdata->spenv);
    pdata->refbase = SP_alloc_globrefs(6);
    pdata->dvar = (Dvar)(pdata+1);
    for (i=0; i<3; i++) {
      DerefArg(t1,X(0),i+1);
      fd_get_var_and_attr(t1,pdata->refbase+2*i);
    }
  }

  /* RESUME HERE */
  dvx = pdata->dvar;
  dvy = dvx+1;
  dvz = dvx+2;
  if (!plan_divmodrem(pdata,w))
    goto ret;
  if (dvar_is_integer(dvy)) {
    if (!mod_integer(pdata,w))
      goto ret;
  } else {    
    for (iter=0; iter<3; iter++) {
      switch (iter) {
      case 0:			/* (X,Y) => Z */
	axmin = (Tgez(xmin) ? xmin : fd_safe_negate_val(xmin));
	axmax = (Tgez(xmax) ? xmax : fd_safe_negate_val(xmax));
	aymin = (Tgez(ymin) ? ymin : fd_safe_negate_val(ymin));
	aymax = (Tgez(ymax) ? ymax : fd_safe_negate_val(ymax));
	switch (ARITH_DISPATCH(xmin,xmax,ymin,ymax)) {
	  /* AUTOMATICALLY GENERATED CASES FOR mod PRUNING DVAR dvz */
	case 0x9: /* inf..-(axmax) * 0..0 */
	case 0x49: /* -(axmin)..-(axmax) * 0..0 */
	case 0x19: /* inf..0 * 0..0 */
	case 0x59: /* -(axmin)..0 * 0..0 */
	case 0x29: /* inf..+(axmax) * 0..0 */
	case 0x39: /* inf..sup * 0..0 */
	case 0x69: /* -(axmin)..+(axmax) * 0..0 */
	case 0x79: /* -(axmin)..sup * 0..0 */
	case 0x99: /* 0..0 * 0..0 */
	case 0xa9: /* 0..+(axmax) * 0..0 */
	case 0xb9: /* 0..sup * 0..0 */
	case 0xe9: /* +(axmin)..+(axmax) * 0..0 */
	case 0xf9: /* +(axmin)..sup * 0..0 */
	  goto ret;
	case 0x3: /* inf..-(axmax) * inf..sup */
	case 0x13: /* inf..0 * inf..sup */
	case 0x23: /* inf..+(axmax) * inf..sup */
	case 0x33: /* inf..sup * inf..sup */
	case 0x63: /* -(axmin)..+(axmax) * inf..sup */
	case 0x73: /* -(axmin)..sup * inf..sup */
	case 0xb3: /* 0..sup * inf..sup */
	case 0xf3: /* +(axmin)..sup * inf..sup */
	default:
	  continue;
	case 0x90: /* 0..0 * inf..-(aymax) */
	case 0x94: /* 0..0 * -(aymin)..-(aymax) */
	case 0x91: /* 0..0 * inf..0 */
	case 0x95: /* 0..0 * -(aymin)..0 */
	case 0x92: /* 0..0 * inf..+(aymax) */
	case 0x93: /* 0..0 * inf..sup */
	case 0x96: /* 0..0 * -(aymin)..+(aymax) */
	case 0x97: /* 0..0 * -(aymin)..sup */
	case 0x9a: /* 0..0 * 0..+(aymax) */
	case 0x9b: /* 0..0 * 0..sup */
	case 0x9e: /* 0..0 * +(aymin)..+(aymax) */
	case 0x9f: /* 0..0 * +(aymin)..sup */
	  newmin = TaggedZero;
	  newmax = newmin;
	  break;
	case 0xab: /* 0..+(axmax) * 0..sup */
	case 0xaf: /* 0..+(axmax) * +(aymin)..sup */
	case 0xeb: /* +(axmin)..+(axmax) * 0..sup */
	  newmin = TaggedZero;
	  newmax = axmax;
	  break;
	case 0xb: /* inf..-(axmax) * 0..sup */
	case 0x4b: /* -(axmin)..-(axmax) * 0..sup */
	case 0xf: /* inf..-(axmax) * +(aymin)..sup */
	case 0x1b: /* inf..0 * 0..sup */
	case 0x5b: /* -(axmin)..0 * 0..sup */
	case 0x1f: /* inf..0 * +(aymin)..sup */
	case 0x5f: /* -(axmin)..0 * +(aymin)..sup */
	case 0x2b: /* inf..+(axmax) * 0..sup */
	case 0x3b: /* inf..sup * 0..sup */
	case 0x6b: /* -(axmin)..+(axmax) * 0..sup */
	case 0x7b: /* -(axmin)..sup * 0..sup */
	case 0x2f: /* inf..+(axmax) * +(aymin)..sup */
	case 0x3f: /* inf..sup * +(aymin)..sup */
	case 0x6f: /* -(axmin)..+(axmax) * +(aymin)..sup */
	case 0x7f: /* -(axmin)..sup * +(aymin)..sup */
	case 0xbb: /* 0..sup * 0..sup */
	case 0xbf: /* 0..sup * +(aymin)..sup */
	case 0xfb: /* +(axmin)..sup * 0..sup */
	case 0xff: /* +(axmin)..sup * +(aymin)..sup */
	  newmin = TaggedZero;
	  newmax = Sup;
	  break;
	case 0xa: /* inf..-(axmax) * 0..+(aymax) */
	case 0x4a: /* -(axmin)..-(axmax) * 0..+(aymax) */
	case 0xe: /* inf..-(axmax) * +(aymin)..+(aymax) */
	case 0x1a: /* inf..0 * 0..+(aymax) */
	case 0x5a: /* -(axmin)..0 * 0..+(aymax) */
	case 0x1e: /* inf..0 * +(aymin)..+(aymax) */
	case 0x5e: /* -(axmin)..0 * +(aymin)..+(aymax) */
	case 0x2a: /* inf..+(axmax) * 0..+(aymax) */
	case 0x3a: /* inf..sup * 0..+(aymax) */
	case 0x6a: /* -(axmin)..+(axmax) * 0..+(aymax) */
	case 0x7a: /* -(axmin)..sup * 0..+(aymax) */
	case 0x2e: /* inf..+(axmax) * +(aymin)..+(aymax) */
	case 0x3e: /* inf..sup * +(aymin)..+(aymax) */
	case 0x6e: /* -(axmin)..+(axmax) * +(aymin)..+(aymax) */
	case 0x7e: /* -(axmin)..sup * +(aymin)..+(aymax) */
	case 0xba: /* 0..sup * 0..+(aymax) */
	case 0xbe: /* 0..sup * +(aymin)..+(aymax) */
	case 0xfa: /* +(axmin)..sup * 0..+(aymax) */
	case 0xfe: /* +(axmin)..sup * +(aymin)..+(aymax) */
	  newmin = TaggedZero;
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  break;
	case 0xaa: /* 0..+(axmax) * 0..+(aymax) */
	case 0xae: /* 0..+(axmax) * +(aymin)..+(aymax) */
	case 0xea: /* +(axmin)..+(axmax) * 0..+(aymax) */
	  newmin = TaggedZero;
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  break;
	case 0x4: /* inf..-(axmax) * -(aymin)..-(aymax) */
	case 0x5: /* inf..-(axmax) * -(aymin)..0 */
	case 0x14: /* inf..0 * -(aymin)..-(aymax) */
	case 0x15: /* inf..0 * -(aymin)..0 */
	case 0x24: /* inf..+(axmax) * -(aymin)..-(aymax) */
	case 0x34: /* inf..sup * -(aymin)..-(aymax) */
	case 0x64: /* -(axmin)..+(axmax) * -(aymin)..-(aymax) */
	case 0x74: /* -(axmin)..sup * -(aymin)..-(aymax) */
	case 0x25: /* inf..+(axmax) * -(aymin)..0 */
	case 0x35: /* inf..sup * -(aymin)..0 */
	case 0x65: /* -(axmin)..+(axmax) * -(aymin)..0 */
	case 0x75: /* -(axmin)..sup * -(aymin)..0 */
	case 0xa4: /* 0..+(axmax) * -(aymin)..-(aymax) */
	case 0xb4: /* 0..sup * -(aymin)..-(aymax) */
	case 0xa5: /* 0..+(axmax) * -(aymin)..0 */
	case 0xb5: /* 0..sup * -(aymin)..0 */
	case 0xf4: /* +(axmin)..sup * -(aymin)..-(aymax) */
	case 0xe5: /* +(axmin)..+(axmax) * -(aymin)..0 */
	case 0xf5: /* +(axmin)..sup * -(aymin)..0 */
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = TaggedZero;
	  break;
	case 0xa7: /* 0..+(axmax) * -(aymin)..sup */
	case 0xe7: /* +(axmin)..+(axmax) * -(aymin)..sup */
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = axmax;
	  break;
	case 0x7: /* inf..-(axmax) * -(aymin)..sup */
	case 0x17: /* inf..0 * -(aymin)..sup */
	case 0x27: /* inf..+(axmax) * -(aymin)..sup */
	case 0x37: /* inf..sup * -(aymin)..sup */
	case 0x67: /* -(axmin)..+(axmax) * -(aymin)..sup */
	case 0x77: /* -(axmin)..sup * -(aymin)..sup */
	case 0xb7: /* 0..sup * -(aymin)..sup */
	case 0xf7: /* +(axmin)..sup * -(aymin)..sup */
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = Sup;
	  break;
	case 0x6: /* inf..-(axmax) * -(aymin)..+(aymax) */
	case 0x16: /* inf..0 * -(aymin)..+(aymax) */
	case 0x26: /* inf..+(axmax) * -(aymin)..+(aymax) */
	case 0x36: /* inf..sup * -(aymin)..+(aymax) */
	case 0x66: /* -(axmin)..+(axmax) * -(aymin)..+(aymax) */
	case 0x76: /* -(axmin)..sup * -(aymin)..+(aymax) */
	case 0xb6: /* 0..sup * -(aymin)..+(aymax) */
	case 0xf6: /* +(axmin)..sup * -(aymin)..+(aymax) */
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  break;
	case 0xa6: /* 0..+(axmax) * -(aymin)..+(aymax) */
	case 0xe6: /* +(axmin)..+(axmax) * -(aymin)..+(aymax) */
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  break;
	case 0x41: /* -(axmin)..-(axmax) * inf..0 */
	case 0x50: /* -(axmin)..0 * inf..-(aymax) */
	case 0x51: /* -(axmin)..0 * inf..0 */
	  newmin = fd_safe_negate(axmin);
	  newmax = TaggedZero;
	  break;
	case 0x43: /* -(axmin)..-(axmax) * inf..sup */
	case 0x53: /* -(axmin)..0 * inf..sup */
	  newmin = fd_safe_negate(axmin);
	  newmax = Sup;
	  break;
	case 0x42: /* -(axmin)..-(axmax) * inf..+(aymax) */
	case 0x52: /* -(axmin)..0 * inf..+(aymax) */
	  newmin = fd_safe_negate(axmin);
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  break;
	case 0x0: /* inf..-(axmax) * inf..-(aymax) */
	case 0x1: /* inf..-(axmax) * inf..0 */
	case 0x10: /* inf..0 * inf..-(aymax) */
	case 0x11: /* inf..0 * inf..0 */
	case 0x20: /* inf..+(axmax) * inf..-(aymax) */
	case 0x30: /* inf..sup * inf..-(aymax) */
	case 0x60: /* -(axmin)..+(axmax) * inf..-(aymax) */
	case 0x70: /* -(axmin)..sup * inf..-(aymax) */
	case 0x21: /* inf..+(axmax) * inf..0 */
	case 0x31: /* inf..sup * inf..0 */
	case 0x61: /* -(axmin)..+(axmax) * inf..0 */
	case 0x71: /* -(axmin)..sup * inf..0 */
	case 0xa0: /* 0..+(axmax) * inf..-(aymax) */
	case 0xb0: /* 0..sup * inf..-(aymax) */
	case 0xa1: /* 0..+(axmax) * inf..0 */
	case 0xb1: /* 0..sup * inf..0 */
	case 0xf0: /* +(axmin)..sup * inf..-(aymax) */
	case 0xe1: /* +(axmin)..+(axmax) * inf..0 */
	case 0xf1: /* +(axmin)..sup * inf..0 */
	  newmin = Inf;
	  newmax = TaggedZero;
	  break;
	case 0xa3: /* 0..+(axmax) * inf..sup */
	case 0xe3: /* +(axmin)..+(axmax) * inf..sup */
	  newmin = Inf;
	  newmax = axmax;
	  break;
	case 0x2: /* inf..-(axmax) * inf..+(aymax) */
	case 0x12: /* inf..0 * inf..+(aymax) */
	case 0x22: /* inf..+(axmax) * inf..+(aymax) */
	case 0x32: /* inf..sup * inf..+(aymax) */
	case 0x62: /* -(axmin)..+(axmax) * inf..+(aymax) */
	case 0x72: /* -(axmin)..sup * inf..+(aymax) */
	case 0xb2: /* 0..sup * inf..+(aymax) */
	case 0xf2: /* +(axmin)..sup * inf..+(aymax) */
	  newmin = Inf;
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  break;
	case 0xa2: /* 0..+(axmax) * inf..+(aymax) */
	case 0xe2: /* +(axmin)..+(axmax) * inf..+(aymax) */
	  newmin = Inf;
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  break;
	case 0x45: /* -(axmin)..-(axmax) * -(aymin)..0 */
	case 0x54: /* -(axmin)..0 * -(aymin)..-(aymax) */
	case 0x55: /* -(axmin)..0 * -(aymin)..0 */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	  newmax = TaggedZero;
	  break;
	case 0x47: /* -(axmin)..-(axmax) * -(aymin)..sup */
	case 0x57: /* -(axmin)..0 * -(aymin)..sup */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	  newmax = Sup;
	  break;
	case 0x46: /* -(axmin)..-(axmax) * -(aymin)..+(aymax) */
	case 0x56: /* -(axmin)..0 * -(aymin)..+(aymax) */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  break;
	case 0xe4: /* +(axmin)..+(axmax) * -(aymin)..-(aymax) */
	  if (Tlt(axmax,aymax)) {
	    newmin = fd_safe_minus(axmin,aymin);
	    newmax = fd_safe_minus(axmax,aymax);
	  } else {
	    newmin = fd_safe_minus(MakeSmall(1),aymin);
	    newmax = TaggedZero;
	  }
	  break;
	case 0xe0: /* +(axmin)..+(axmax) * inf..-(aymax) */
	  if (Tlt(axmax,aymax)) {
	    newmin = Inf;
	    newmax = fd_safe_minus(axmax,aymax);
	  } else {
	    newmin = Inf;
	    newmax = TaggedZero;
	  }
	  break;
	case 0xef: /* +(axmin)..+(axmax) * +(aymin)..sup */
	  if (Tlt(axmax,aymin)) {
	    newmin = axmin;
	    newmax = axmax;
	  } else {
	    newmin = TaggedZero;
	    newmax = axmax;
	  }
	  break;
	case 0xee: /* +(axmin)..+(axmax) * +(aymin)..+(aymax) */
	  if (Tlt(axmax,aymin)) {
	    newmin = axmin;
	    newmax = axmax;
	  } else {
	    newmin = TaggedZero;
	    newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  }
	  break;
	case 0x40: /* -(axmin)..-(axmax) * inf..-(aymax) */
	  if (Tlt(axmin,aymax)) {
	    newmin = fd_safe_negate(axmin);
	    newmax = fd_safe_negate(axmax);
	  } else {
	    newmin = fd_safe_negate(axmin);
	    newmax = TaggedZero;
	  }
	  break;
	case 0x44: /* -(axmin)..-(axmax) * -(aymin)..-(aymax) */
	  if (Tlt(axmin,aymax)) {
	    newmin = fd_safe_negate(axmin);
	    newmax = fd_safe_negate(axmax);
	  } else {
	    newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	    newmax = TaggedZero;
	  }
	  break;
	case 0x4f: /* -(axmin)..-(axmax) * +(aymin)..sup */
	  if (Tlt(axmin,aymin)) {
	    newmin = fd_safe_minus(aymin,axmin);
	    newmax = Sup;
	  } else {
	    newmin = TaggedZero;
	    newmax = Sup;
	  }
	  break;
	case 0x4e: /* -(axmin)..-(axmax) * +(aymin)..+(aymax) */
	  if (Tlt(axmin,aymin)) {
	    newmin = fd_safe_minus(aymin,axmin);
	    newmax = fd_safe_minus(aymax,axmax);
	  } else {
	    newmin = TaggedZero;
	    newmax = fd_safe_minus(aymax,MakeSmall(1));
	  }
	  break;
	}
	if (dvar_fix_interval_t(dvz, newmin, newmax)<0) {
	  if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	    fd.fd_overflow = TRUE;
	  goto ret;
	}
	break;
      case 1:			/* (X,Z) => Y */
	axmin = (Tgez(xmin) ? xmin : fd_safe_negate_val(xmin));
	axmax = (Tgez(xmax) ? xmax : fd_safe_negate_val(xmax));
	azmin = (Tgez(zmin) ? zmin : fd_safe_negate_val(zmin));
	azmax = (Tgez(zmax) ? zmax : fd_safe_negate_val(zmax));
	switch (ARITH_DISPATCH(xmin,xmax,zmin,zmax)) {
	  /* AUTOMATICALLY GENERATED CASES FOR mod PRUNING DVAR dvy */
	case 0x90: /* 0..0 * inf..-(azmax) */
	case 0x94: /* 0..0 * -(azmin)..-(azmax) */
	case 0x9e: /* 0..0 * +(azmin)..+(azmax) */
	case 0x9f: /* 0..0 * +(azmin)..sup */
	  goto ret;
	case 0x1: /* inf..-(axmax) * inf..0 */
	case 0x5: /* inf..-(axmax) * -(azmin)..0 */
	case 0x2: /* inf..-(axmax) * inf..+(azmax) */
	case 0x3: /* inf..-(axmax) * inf..sup */
	case 0x6: /* inf..-(axmax) * -(azmin)..+(azmax) */
	case 0x7: /* inf..-(axmax) * -(azmin)..sup */
	case 0x43: /* -(axmin)..-(axmax) * inf..sup */
	case 0x9: /* inf..-(axmax) * 0..0 */
	case 0xa: /* inf..-(axmax) * 0..+(azmax) */
	case 0xb: /* inf..-(axmax) * 0..sup */
	case 0x11: /* inf..0 * inf..0 */
	case 0x15: /* inf..0 * -(azmin)..0 */
	case 0x51: /* -(axmin)..0 * inf..0 */
	case 0x55: /* -(axmin)..0 * -(azmin)..0 */
	case 0x12: /* inf..0 * inf..+(azmax) */
	case 0x13: /* inf..0 * inf..sup */
	case 0x16: /* inf..0 * -(azmin)..+(azmax) */
	case 0x17: /* inf..0 * -(azmin)..sup */
	case 0x52: /* -(axmin)..0 * inf..+(azmax) */
	case 0x53: /* -(axmin)..0 * inf..sup */
	case 0x56: /* -(axmin)..0 * -(azmin)..+(azmax) */
	case 0x57: /* -(axmin)..0 * -(azmin)..sup */
	case 0x19: /* inf..0 * 0..0 */
	case 0x59: /* -(axmin)..0 * 0..0 */
	case 0x1a: /* inf..0 * 0..+(azmax) */
	case 0x1b: /* inf..0 * 0..sup */
	case 0x5a: /* -(axmin)..0 * 0..+(azmax) */
	case 0x5b: /* -(axmin)..0 * 0..sup */
	case 0x21: /* inf..+(axmax) * inf..0 */
	case 0x25: /* inf..+(axmax) * -(azmin)..0 */
	case 0x31: /* inf..sup * inf..0 */
	case 0x35: /* inf..sup * -(azmin)..0 */
	case 0x61: /* -(axmin)..+(axmax) * inf..0 */
	case 0x65: /* -(axmin)..+(axmax) * -(azmin)..0 */
	case 0x71: /* -(axmin)..sup * inf..0 */
	case 0x75: /* -(axmin)..sup * -(azmin)..0 */
	case 0x22: /* inf..+(axmax) * inf..+(azmax) */
	case 0x23: /* inf..+(axmax) * inf..sup */
	case 0x26: /* inf..+(axmax) * -(azmin)..+(azmax) */
	case 0x27: /* inf..+(axmax) * -(azmin)..sup */
	case 0x32: /* inf..sup * inf..+(azmax) */
	case 0x33: /* inf..sup * inf..sup */
	case 0x36: /* inf..sup * -(azmin)..+(azmax) */
	case 0x37: /* inf..sup * -(azmin)..sup */
	case 0x62: /* -(axmin)..+(axmax) * inf..+(azmax) */
	case 0x63: /* -(axmin)..+(axmax) * inf..sup */
	case 0x66: /* -(axmin)..+(axmax) * -(azmin)..+(azmax) */
	case 0x67: /* -(axmin)..+(axmax) * -(azmin)..sup */
	case 0x72: /* -(axmin)..sup * inf..+(azmax) */
	case 0x73: /* -(axmin)..sup * inf..sup */
	case 0x76: /* -(axmin)..sup * -(azmin)..+(azmax) */
	case 0x77: /* -(axmin)..sup * -(azmin)..sup */
	case 0x29: /* inf..+(axmax) * 0..0 */
	case 0x39: /* inf..sup * 0..0 */
	case 0x69: /* -(axmin)..+(axmax) * 0..0 */
	case 0x79: /* -(axmin)..sup * 0..0 */
	case 0x2a: /* inf..+(axmax) * 0..+(azmax) */
	case 0x2b: /* inf..+(axmax) * 0..sup */
	case 0x3a: /* inf..sup * 0..+(azmax) */
	case 0x3b: /* inf..sup * 0..sup */
	case 0x6a: /* -(axmin)..+(axmax) * 0..+(azmax) */
	case 0x6b: /* -(axmin)..+(axmax) * 0..sup */
	case 0x7a: /* -(axmin)..sup * 0..+(azmax) */
	case 0x7b: /* -(axmin)..sup * 0..sup */
	case 0x91: /* 0..0 * inf..0 */
	case 0x95: /* 0..0 * -(azmin)..0 */
	case 0x92: /* 0..0 * inf..+(azmax) */
	case 0x93: /* 0..0 * inf..sup */
	case 0x96: /* 0..0 * -(azmin)..+(azmax) */
	case 0x97: /* 0..0 * -(azmin)..sup */
	case 0x99: /* 0..0 * 0..0 */
	case 0x9a: /* 0..0 * 0..+(azmax) */
	case 0x9b: /* 0..0 * 0..sup */
	case 0xa1: /* 0..+(axmax) * inf..0 */
	case 0xa5: /* 0..+(axmax) * -(azmin)..0 */
	case 0xb1: /* 0..sup * inf..0 */
	case 0xb5: /* 0..sup * -(azmin)..0 */
	case 0xa2: /* 0..+(axmax) * inf..+(azmax) */
	case 0xa3: /* 0..+(axmax) * inf..sup */
	case 0xa6: /* 0..+(axmax) * -(azmin)..+(azmax) */
	case 0xa7: /* 0..+(axmax) * -(azmin)..sup */
	case 0xb2: /* 0..sup * inf..+(azmax) */
	case 0xb3: /* 0..sup * inf..sup */
	case 0xb6: /* 0..sup * -(azmin)..+(azmax) */
	case 0xb7: /* 0..sup * -(azmin)..sup */
	case 0xa9: /* 0..+(axmax) * 0..0 */
	case 0xb9: /* 0..sup * 0..0 */
	case 0xaa: /* 0..+(axmax) * 0..+(azmax) */
	case 0xab: /* 0..+(axmax) * 0..sup */
	case 0xba: /* 0..sup * 0..+(azmax) */
	case 0xbb: /* 0..sup * 0..sup */
	case 0xf1: /* +(axmin)..sup * inf..0 */
	case 0xf5: /* +(axmin)..sup * -(azmin)..0 */
	case 0xe3: /* +(axmin)..+(axmax) * inf..sup */
	case 0xf2: /* +(axmin)..sup * inf..+(azmax) */
	case 0xf3: /* +(axmin)..sup * inf..sup */
	case 0xf6: /* +(axmin)..sup * -(azmin)..+(azmax) */
	case 0xf7: /* +(axmin)..sup * -(azmin)..sup */
	case 0xf9: /* +(axmin)..sup * 0..0 */
	case 0xfa: /* +(axmin)..sup * 0..+(azmax) */
	case 0xfb: /* +(axmin)..sup * 0..sup */
	default:
	  continue;
	case 0xe: /* inf..-(axmax) * +(azmin)..+(azmax) */
	case 0xf: /* inf..-(axmax) * +(azmin)..sup */
	case 0x4f: /* -(axmin)..-(axmax) * +(azmin)..sup */
	case 0x1e: /* inf..0 * +(azmin)..+(azmax) */
	case 0x1f: /* inf..0 * +(azmin)..sup */
	case 0x5f: /* -(axmin)..0 * +(azmin)..sup */
	case 0x2e: /* inf..+(axmax) * +(azmin)..+(azmax) */
	case 0x2f: /* inf..+(axmax) * +(azmin)..sup */
	case 0x3e: /* inf..sup * +(azmin)..+(azmax) */
	case 0x3f: /* inf..sup * +(azmin)..sup */
	case 0x6f: /* -(axmin)..+(axmax) * +(azmin)..sup */
	case 0x7e: /* -(axmin)..sup * +(azmin)..+(azmax) */
	case 0x7f: /* -(axmin)..sup * +(azmin)..sup */
	case 0xbe: /* 0..sup * +(azmin)..+(azmax) */
	case 0xbf: /* 0..sup * +(azmin)..sup */
	case 0xfe: /* +(axmin)..sup * +(azmin)..+(azmax) */
	case 0xff: /* +(axmin)..sup * +(azmin)..sup */
	  newmin = fd_safe_plus(azmin,MakeSmall(1));
	  newmax = Sup;
	  break;
	case 0x4e: /* -(axmin)..-(axmax) * +(azmin)..+(azmax) */
	case 0x5e: /* -(axmin)..0 * +(azmin)..+(azmax) */
	  newmin = fd_safe_plus(azmin,MakeSmall(1));
	  newmax = fd_safe_plus(axmin,azmax);
	  break;
	case 0xe9: /* +(axmin)..+(axmax) * 0..0 */
	  newmin = fd_safe_negate(axmax);
	  newmax = axmax;
	  break;
	case 0xeb: /* +(axmin)..+(axmax) * 0..sup */
	  newmin = fd_safe_negate(axmax);
	  newmax = Sup;
	  break;
	case 0x49: /* -(axmin)..-(axmax) * 0..0 */
	  newmin = fd_safe_negate(axmin);
	  newmax = axmin;
	  break;
	case 0x4b: /* -(axmin)..-(axmax) * 0..sup */
	  newmin = fd_safe_negate(axmin);
	  newmax = Sup;
	  break;
	case 0x4a: /* -(axmin)..-(axmax) * 0..+(azmax) */
	  newmin = fd_safe_negate(axmin);
	  newmax = fd_safe_plus(axmin,azmax);
	  break;
	case 0xe1: /* +(axmin)..+(axmax) * inf..0 */
	  newmin = Inf;
	  newmax = axmax;
	  break;
	case 0x41: /* -(axmin)..-(axmax) * inf..0 */
	  newmin = Inf;
	  newmax = axmin;
	  break;
	case 0x42: /* -(axmin)..-(axmax) * inf..+(azmax) */
	  newmin = Inf;
	  newmax = fd_safe_plus(axmin,azmax);
	  break;
	case 0x0: /* inf..-(axmax) * inf..-(azmax) */
	case 0x4: /* inf..-(axmax) * -(azmin)..-(azmax) */
	case 0x10: /* inf..0 * inf..-(azmax) */
	case 0x14: /* inf..0 * -(azmin)..-(azmax) */
	case 0x20: /* inf..+(axmax) * inf..-(azmax) */
	case 0x24: /* inf..+(axmax) * -(azmin)..-(azmax) */
	case 0x30: /* inf..sup * inf..-(azmax) */
	case 0x34: /* inf..sup * -(azmin)..-(azmax) */
	case 0x60: /* -(axmin)..+(axmax) * inf..-(azmax) */
	case 0x70: /* -(axmin)..sup * inf..-(azmax) */
	case 0x74: /* -(axmin)..sup * -(azmin)..-(azmax) */
	case 0xa0: /* 0..+(axmax) * inf..-(azmax) */
	case 0xb0: /* 0..sup * inf..-(azmax) */
	case 0xb4: /* 0..sup * -(azmin)..-(azmax) */
	case 0xe0: /* +(axmin)..+(axmax) * inf..-(azmax) */
	case 0xf0: /* +(axmin)..sup * inf..-(azmax) */
	case 0xf4: /* +(axmin)..sup * -(azmin)..-(azmax) */
	  newmin = Inf;
	  newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  break;
	case 0xe5: /* +(axmin)..+(axmax) * -(azmin)..0 */
	  newmin = fd_safe_negate(fd_safe_plus(axmax,azmin));
	  newmax = axmax;
	  break;
	case 0xe7: /* +(axmin)..+(axmax) * -(azmin)..sup */
	  newmin = fd_safe_negate(fd_safe_plus(axmax,azmin));
	  newmax = Sup;
	  break;
	case 0xa4: /* 0..+(axmax) * -(azmin)..-(azmax) */
	case 0xe4: /* +(axmin)..+(axmax) * -(azmin)..-(azmax) */
	  newmin = fd_safe_negate(fd_safe_plus(axmax,azmin));
	  newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  break;
	case 0x47: /* -(axmin)..-(axmax) * -(azmin)..sup */
	  if (Tle(axmax,azmin)) {
	    continue;
	  } else {
	    newmin = fd_safe_negate(axmin);
	    newmax = Sup;
	  }
	  break;
	case 0x45: /* -(axmin)..-(axmax) * -(azmin)..0 */
	  if (Tle(axmax,azmin)) {
	    newmin = Inf;
	    newmax = axmin;
	  } else {
	    newmin = fd_safe_negate(axmin);
	    newmax = axmin;
	  }
	  break;
	case 0x46: /* -(axmin)..-(axmax) * -(azmin)..+(azmax) */
	  if (Tle(axmax,azmin)) {
	    newmin = Inf;
	    newmax = fd_safe_plus(axmin,azmax);
	  } else {
	    newmin = fd_safe_negate(axmin);
	    newmax = fd_safe_plus(axmin,azmax);
	  }
	  break;
	case 0xe2: /* +(axmin)..+(axmax) * inf..+(azmax) */
	  if (Tle(axmin,azmax)) {
	    continue;
	  } else {
	    newmin = Inf;
	    newmax = axmax;
	  }
	  break;
	case 0xea: /* +(axmin)..+(axmax) * 0..+(azmax) */
	  if (Tle(axmin,azmax)) {
	    newmin = fd_safe_negate(axmax);
	    newmax = Sup;
	  } else {
	    newmin = fd_safe_negate(axmax);
	    newmax = axmax;
	  }
	  break;
	case 0xe6: /* +(axmin)..+(axmax) * -(azmin)..+(azmax) */
	  if (Tle(axmin,azmax)) {
	    newmin = fd_safe_negate(fd_safe_plus(axmax,azmin));
	    newmax = Sup;
	  } else {
	    newmin = fd_safe_negate(fd_safe_plus(axmax,azmin));
	    newmax = axmax;
	  }
	  break;
	case 0x50: /* -(axmin)..0 * inf..-(azmax) */
	case 0x54: /* -(axmin)..0 * -(azmin)..-(azmax) */
	  if (Tle(azmax,axmin)) {
	    newmin = Inf;
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  } else {
	    newmin = fd_safe_minus(azmax,axmin);
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  }
	  break;
	case 0x64: /* -(axmin)..+(axmax) * -(azmin)..-(azmax) */
	  if (Tle(azmax,axmin)) {
	    newmin = Inf;
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  } else {
	    newmin = fd_safe_negate(fd_safe_plus(axmax,azmin));
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  }
	  break;
	case 0x6e: /* -(axmin)..+(axmax) * +(azmin)..+(azmax) */
	  if (Tle(azmin,axmax)) {
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = Sup;
	  } else {
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = fd_safe_plus(axmin,azmax);
	  }
	  break;
	case 0xae: /* 0..+(axmax) * +(azmin)..+(azmax) */
	case 0xaf: /* 0..+(axmax) * +(azmin)..sup */
	  if (Tle(azmin,axmax)) {
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = Sup;
	  } else {
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = fd_safe_minus(axmax,azmin);
	  }
	  break;
	case 0x40: /* -(axmin)..-(axmax) * inf..-(azmax) */
	  if (Tle(fd_safe_max(axmax,azmax),axmin)) {
	    newmin = fd_safe_negate(axmax);
	    newmax = fd_safe_negate(fd_safe_plus(fd_safe_minus(axmin,azmax),MakeSmall(1)));
	    if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	      goto ret;
	    newmin = Inf;
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  } else {
	    newmin = fd_safe_minus(azmax,axmin);
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  }
	  break;
	case 0x44: /* -(axmin)..-(axmax) * -(azmin)..-(azmax) */
	  if (Tle(fd_safe_max(axmax,azmax),fd_safe_min(axmin,azmin))) {
	    newmin = fd_safe_negate(axmax);
	    newmax = fd_safe_negate(fd_safe_plus(fd_safe_minus(axmin,azmax),MakeSmall(1)));
	    if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	      goto ret;
	    newmin = Inf;
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  } else {
	    newmin = fd_safe_minus(azmax,axmin);
	    newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  }
	  break;
	case 0xef: /* +(axmin)..+(axmax) * +(azmin)..sup */
	  if (Tle(fd_safe_max(axmin,azmin),axmax)) {
	    newmin = fd_safe_plus(fd_safe_minus(axmax,azmin),MakeSmall(1));
	    newmax = axmin;
	    if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	      goto ret;
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = Sup;
	  } else {
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = fd_safe_minus(axmax,azmin);
	  }
	  break;
	case 0xee: /* +(axmin)..+(axmax) * +(azmin)..+(azmax) */
	  if (Tle(fd_safe_max(axmin,azmin),fd_safe_min(axmax,azmax))) {
	    newmin = fd_safe_plus(fd_safe_minus(axmax,azmin),MakeSmall(1));
	    newmax = axmin;
	    if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	      goto ret;
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = Sup;
	  } else {
	    newmin = fd_safe_plus(azmin,MakeSmall(1));
	    newmax = fd_safe_minus(axmax,azmin);
	  }
	  break;
	}
	if (dvar_fix_interval_t(dvy, newmin, newmax)<0) {
	  if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	    fd.fd_overflow = TRUE;
	  goto ret;
	}
	break;
      case 2:			/* (Y,Z) => X */
	aymin = (Tgez(ymin) ? ymin : fd_safe_negate_val(ymin));
	aymax = (Tgez(ymax) ? ymax : fd_safe_negate_val(ymax));
	azmin = (Tgez(zmin) ? zmin : fd_safe_negate_val(zmin));
	azmax = (Tgez(zmax) ? zmax : fd_safe_negate_val(zmax));
	switch (ARITH_DISPATCH(ymin,ymax,zmin,zmax)) {
	  /* AUTOMATICALLY GENERATED CASES FOR mod PRUNING DVAR dvx */
	case 0xe: /* inf..-(aymax) * +(azmin)..+(azmax) */
	case 0xf: /* inf..-(aymax) * +(azmin)..sup */
	case 0x4e: /* -(aymin)..-(aymax) * +(azmin)..+(azmax) */
	case 0x4f: /* -(aymin)..-(aymax) * +(azmin)..sup */
	case 0x1e: /* inf..0 * +(azmin)..+(azmax) */
	case 0x1f: /* inf..0 * +(azmin)..sup */
	case 0x5e: /* -(aymin)..0 * +(azmin)..+(azmax) */
	case 0x5f: /* -(aymin)..0 * +(azmin)..sup */
	case 0x90: /* 0..0 * inf..-(azmax) */
	case 0x94: /* 0..0 * -(azmin)..-(azmax) */
	case 0x91: /* 0..0 * inf..0 */
	case 0x95: /* 0..0 * -(azmin)..0 */
	case 0x92: /* 0..0 * inf..+(azmax) */
	case 0x93: /* 0..0 * inf..sup */
	case 0x96: /* 0..0 * -(azmin)..+(azmax) */
	case 0x97: /* 0..0 * -(azmin)..sup */
	case 0x99: /* 0..0 * 0..0 */
	case 0x9a: /* 0..0 * 0..+(azmax) */
	case 0x9b: /* 0..0 * 0..sup */
	case 0x9e: /* 0..0 * +(azmin)..+(azmax) */
	case 0x9f: /* 0..0 * +(azmin)..sup */
	case 0xa0: /* 0..+(aymax) * inf..-(azmax) */
	case 0xa4: /* 0..+(aymax) * -(azmin)..-(azmax) */
	case 0xb0: /* 0..sup * inf..-(azmax) */
	case 0xb4: /* 0..sup * -(azmin)..-(azmax) */
	case 0xe0: /* +(aymin)..+(aymax) * inf..-(azmax) */
	case 0xe4: /* +(aymin)..+(aymax) * -(azmin)..-(azmax) */
	case 0xf0: /* +(aymin)..sup * inf..-(azmax) */
	case 0xf4: /* +(aymin)..sup * -(azmin)..-(azmax) */
	  goto ret;
	case 0x1: /* inf..-(aymax) * inf..0 */
	case 0x5: /* inf..-(aymax) * -(azmin)..0 */
	case 0x41: /* -(aymin)..-(aymax) * inf..0 */
	case 0x45: /* -(aymin)..-(aymax) * -(azmin)..0 */
	case 0x2: /* inf..-(aymax) * inf..+(azmax) */
	case 0x3: /* inf..-(aymax) * inf..sup */
	case 0x6: /* inf..-(aymax) * -(azmin)..+(azmax) */
	case 0x7: /* inf..-(aymax) * -(azmin)..sup */
	case 0x42: /* -(aymin)..-(aymax) * inf..+(azmax) */
	case 0x43: /* -(aymin)..-(aymax) * inf..sup */
	case 0x46: /* -(aymin)..-(aymax) * -(azmin)..+(azmax) */
	case 0x47: /* -(aymin)..-(aymax) * -(azmin)..sup */
	case 0x9: /* inf..-(aymax) * 0..0 */
	case 0x49: /* -(aymin)..-(aymax) * 0..0 */
	case 0xa: /* inf..-(aymax) * 0..+(azmax) */
	case 0xb: /* inf..-(aymax) * 0..sup */
	case 0x4a: /* -(aymin)..-(aymax) * 0..+(azmax) */
	case 0x4b: /* -(aymin)..-(aymax) * 0..sup */
	case 0x11: /* inf..0 * inf..0 */
	case 0x15: /* inf..0 * -(azmin)..0 */
	case 0x51: /* -(aymin)..0 * inf..0 */
	case 0x55: /* -(aymin)..0 * -(azmin)..0 */
	case 0x12: /* inf..0 * inf..+(azmax) */
	case 0x13: /* inf..0 * inf..sup */
	case 0x16: /* inf..0 * -(azmin)..+(azmax) */
	case 0x17: /* inf..0 * -(azmin)..sup */
	case 0x52: /* -(aymin)..0 * inf..+(azmax) */
	case 0x53: /* -(aymin)..0 * inf..sup */
	case 0x56: /* -(aymin)..0 * -(azmin)..+(azmax) */
	case 0x57: /* -(aymin)..0 * -(azmin)..sup */
	case 0x19: /* inf..0 * 0..0 */
	case 0x59: /* -(aymin)..0 * 0..0 */
	case 0x1a: /* inf..0 * 0..+(azmax) */
	case 0x1b: /* inf..0 * 0..sup */
	case 0x5a: /* -(aymin)..0 * 0..+(azmax) */
	case 0x5b: /* -(aymin)..0 * 0..sup */
	case 0x21: /* inf..+(aymax) * inf..0 */
	case 0x25: /* inf..+(aymax) * -(azmin)..0 */
	case 0x31: /* inf..sup * inf..0 */
	case 0x35: /* inf..sup * -(azmin)..0 */
	case 0x61: /* -(aymin)..+(aymax) * inf..0 */
	case 0x65: /* -(aymin)..+(aymax) * -(azmin)..0 */
	case 0x71: /* -(aymin)..sup * inf..0 */
	case 0x75: /* -(aymin)..sup * -(azmin)..0 */
	case 0x22: /* inf..+(aymax) * inf..+(azmax) */
	case 0x23: /* inf..+(aymax) * inf..sup */
	case 0x26: /* inf..+(aymax) * -(azmin)..+(azmax) */
	case 0x27: /* inf..+(aymax) * -(azmin)..sup */
	case 0x32: /* inf..sup * inf..+(azmax) */
	case 0x33: /* inf..sup * inf..sup */
	case 0x36: /* inf..sup * -(azmin)..+(azmax) */
	case 0x37: /* inf..sup * -(azmin)..sup */
	case 0x62: /* -(aymin)..+(aymax) * inf..+(azmax) */
	case 0x63: /* -(aymin)..+(aymax) * inf..sup */
	case 0x66: /* -(aymin)..+(aymax) * -(azmin)..+(azmax) */
	case 0x67: /* -(aymin)..+(aymax) * -(azmin)..sup */
	case 0x72: /* -(aymin)..sup * inf..+(azmax) */
	case 0x73: /* -(aymin)..sup * inf..sup */
	case 0x76: /* -(aymin)..sup * -(azmin)..+(azmax) */
	case 0x77: /* -(aymin)..sup * -(azmin)..sup */
	case 0x29: /* inf..+(aymax) * 0..0 */
	case 0x39: /* inf..sup * 0..0 */
	case 0x69: /* -(aymin)..+(aymax) * 0..0 */
	case 0x79: /* -(aymin)..sup * 0..0 */
	case 0x2a: /* inf..+(aymax) * 0..+(azmax) */
	case 0x2b: /* inf..+(aymax) * 0..sup */
	case 0x3a: /* inf..sup * 0..+(azmax) */
	case 0x3b: /* inf..sup * 0..sup */
	case 0x6a: /* -(aymin)..+(aymax) * 0..+(azmax) */
	case 0x6b: /* -(aymin)..+(aymax) * 0..sup */
	case 0x7a: /* -(aymin)..sup * 0..+(azmax) */
	case 0x7b: /* -(aymin)..sup * 0..sup */
	case 0xa1: /* 0..+(aymax) * inf..0 */
	case 0xa5: /* 0..+(aymax) * -(azmin)..0 */
	case 0xb1: /* 0..sup * inf..0 */
	case 0xb5: /* 0..sup * -(azmin)..0 */
	case 0xa2: /* 0..+(aymax) * inf..+(azmax) */
	case 0xa3: /* 0..+(aymax) * inf..sup */
	case 0xa6: /* 0..+(aymax) * -(azmin)..+(azmax) */
	case 0xa7: /* 0..+(aymax) * -(azmin)..sup */
	case 0xb2: /* 0..sup * inf..+(azmax) */
	case 0xb3: /* 0..sup * inf..sup */
	case 0xb6: /* 0..sup * -(azmin)..+(azmax) */
	case 0xb7: /* 0..sup * -(azmin)..sup */
	case 0xa9: /* 0..+(aymax) * 0..0 */
	case 0xb9: /* 0..sup * 0..0 */
	case 0xaa: /* 0..+(aymax) * 0..+(azmax) */
	case 0xab: /* 0..+(aymax) * 0..sup */
	case 0xba: /* 0..sup * 0..+(azmax) */
	case 0xbb: /* 0..sup * 0..sup */
	case 0xe1: /* +(aymin)..+(aymax) * inf..0 */
	case 0xe5: /* +(aymin)..+(aymax) * -(azmin)..0 */
	case 0xf1: /* +(aymin)..sup * inf..0 */
	case 0xf5: /* +(aymin)..sup * -(azmin)..0 */
	case 0xe2: /* +(aymin)..+(aymax) * inf..+(azmax) */
	case 0xe3: /* +(aymin)..+(aymax) * inf..sup */
	case 0xe6: /* +(aymin)..+(aymax) * -(azmin)..+(azmax) */
	case 0xe7: /* +(aymin)..+(aymax) * -(azmin)..sup */
	case 0xf2: /* +(aymin)..sup * inf..+(azmax) */
	case 0xf3: /* +(aymin)..sup * inf..sup */
	case 0xf6: /* +(aymin)..sup * -(azmin)..+(azmax) */
	case 0xf7: /* +(aymin)..sup * -(azmin)..sup */
	case 0xe9: /* +(aymin)..+(aymax) * 0..0 */
	case 0xf9: /* +(aymin)..sup * 0..0 */
	case 0xea: /* +(aymin)..+(aymax) * 0..+(azmax) */
	case 0xeb: /* +(aymin)..+(aymax) * 0..sup */
	case 0xfa: /* +(aymin)..sup * 0..+(azmax) */
	case 0xfb: /* +(aymin)..sup * 0..sup */
	default:
	  continue;
	case 0x0: /* inf..-(aymax) * inf..-(azmax) */
	case 0x4: /* inf..-(aymax) * -(azmin)..-(azmax) */
	case 0x40: /* -(aymin)..-(aymax) * inf..-(azmax) */
	case 0x44: /* -(aymin)..-(aymax) * -(azmin)..-(azmax) */
	case 0x10: /* inf..0 * inf..-(azmax) */
	case 0x14: /* inf..0 * -(azmin)..-(azmax) */
	case 0x50: /* -(aymin)..0 * inf..-(azmax) */
	case 0x54: /* -(aymin)..0 * -(azmin)..-(azmax) */
	case 0x20: /* inf..+(aymax) * inf..-(azmax) */
	case 0x24: /* inf..+(aymax) * -(azmin)..-(azmax) */
	case 0x30: /* inf..sup * inf..-(azmax) */
	case 0x34: /* inf..sup * -(azmin)..-(azmax) */
	case 0x60: /* -(aymin)..+(aymax) * inf..-(azmax) */
	case 0x64: /* -(aymin)..+(aymax) * -(azmin)..-(azmax) */
	case 0x70: /* -(aymin)..sup * inf..-(azmax) */
	case 0x74: /* -(aymin)..sup * -(azmin)..-(azmax) */
	case 0x2e: /* inf..+(aymax) * +(azmin)..+(azmax) */
	case 0x2f: /* inf..+(aymax) * +(azmin)..sup */
	case 0x3e: /* inf..sup * +(azmin)..+(azmax) */
	case 0x3f: /* inf..sup * +(azmin)..sup */
	case 0x6e: /* -(aymin)..+(aymax) * +(azmin)..+(azmax) */
	case 0x6f: /* -(aymin)..+(aymax) * +(azmin)..sup */
	case 0x7e: /* -(aymin)..sup * +(azmin)..+(azmax) */
	case 0x7f: /* -(aymin)..sup * +(azmin)..sup */
	case 0xae: /* 0..+(aymax) * +(azmin)..+(azmax) */
	case 0xaf: /* 0..+(aymax) * +(azmin)..sup */
	case 0xbe: /* 0..sup * +(azmin)..+(azmax) */
	case 0xbf: /* 0..sup * +(azmin)..sup */
	case 0xee: /* +(aymin)..+(aymax) * +(azmin)..+(azmax) */
	case 0xef: /* +(aymin)..+(aymax) * +(azmin)..sup */
	case 0xfe: /* +(aymin)..sup * +(azmin)..+(azmax) */
	case 0xff: /* +(aymin)..sup * +(azmin)..sup */
	  newmin = TaggedZero;
	  newmax = newmin;
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	}
	break;
      }
    }
  }
#if 0
  /* shaving */
  if (!shave_bounds(w,dvx,1))
    goto ret;
#endif
  if (dvar_is_integer(dvx) && dvar_is_integer(dvy) && dvar_is_integer(dvz)) {
    ent = fast_modi(dvar_min_l(dvx),dvar_min_l(dvy))==dvar_min_l(dvz) ? 1 : -1;
  } else {
    ent = 0;
  }
  for (i=0; i<3; i++)
    dvar_pruning_done(w,dvx+i);
  for (i=0; i<3; i++)
    dvar_export(w,dvx+i);
 ret:
  if (ent==1)
    Pfree;
  dvar_export_done(w,Actions, ent);
}

/*
  '$fd_remainder'(State0, State, Actions).
  State = state(X-XMut, Y-YMut, Z-ZMut, B-Bmut)
  Z #= X rem Y AND (Y=0 implies B=0)
*/
void SPCDECL
prolog_fd_remainder MAGIC (HIDDEN_PROTO
			   SP_term_ref State,
			   SP_term_ref NewState,
			   SP_term_ref Actions)
{
  WAMENV;
  Dvar dvx, dvy, dvz;
  TAGGED newmin, newmax, axmin, axmax, aymin, aymax, azmin, azmax;
  int i, iter;
  TAGGED handle, t1;
  SP_BOOL committed;
  struct arith_data *pdata;
  int ent = -1;			/* disentailed unless otherwise */

  (void)State;                 /* [PM] 3.9b5 avoid -Wunused */
/*    X(0) = RefTerm(State0); */
  w->numstack_end = NULL;
  dvar_export_start(w);
  RefTerm(NewState) = fd_static_output_state(w,&handle,&committed);
  if (!IsVar(handle)) {		/* got [Flag | '$free'(Ptr)] */
    pdata = Pdata(struct arith_data,handle);
  } else {			/* build persistent state */
    pdata = Palloc(struct arith_data, 4*sizeof(struct dvar), handle);
    pdata->destructor = arith_destructor;
    pdata->nrefs = 6;
    FD_STORE_SPENV(pdata->spenv);
    pdata->refbase = SP_alloc_globrefs(6);
    pdata->dvar = (Dvar)(pdata+1);
    for (i=0; i<3; i++) {
      DerefArg(t1,X(0),i+1);
      fd_get_var_and_attr(t1,pdata->refbase+2*i);
    }
  }

  /* RESUME HERE */
  dvx = pdata->dvar;
  dvy = dvx+1;
  dvz = dvx+2;
  if (!plan_divmodrem(pdata,w))
    goto ret;
  if (dvar_is_integer(dvy)) {
    if (!rem_integer(pdata,w))
      goto ret;
  } else {    
    for (iter=0; iter<3; iter++) {
      switch (iter) {
      case 0:			/* (X,Y) => Z */
	axmin = (Tgez(xmin) ? xmin : fd_safe_negate_val(xmin));
	axmax = (Tgez(xmax) ? xmax : fd_safe_negate_val(xmax));
	aymin = (Tgez(ymin) ? ymin : fd_safe_negate_val(ymin));
	aymax = (Tgez(ymax) ? ymax : fd_safe_negate_val(ymax));
	switch (ARITH_DISPATCH(xmin,xmax,ymin,ymax)) {
	  /* AUTOMATICALLY GENERATED CASES FOR rem PRUNING DVAR dvz */
	case 0x9: /* inf..-(axmax) * 0..0 */
	case 0x49: /* -(axmin)..-(axmax) * 0..0 */
	case 0x19: /* inf..0 * 0..0 */
	case 0x59: /* -(axmin)..0 * 0..0 */
	case 0x29: /* inf..+(axmax) * 0..0 */
	case 0x39: /* inf..sup * 0..0 */
	case 0x69: /* -(axmin)..+(axmax) * 0..0 */
	case 0x79: /* -(axmin)..sup * 0..0 */
	case 0x99: /* 0..0 * 0..0 */
	case 0xa9: /* 0..+(axmax) * 0..0 */
	case 0xb9: /* 0..sup * 0..0 */
	case 0xe9: /* +(axmin)..+(axmax) * 0..0 */
	case 0xf9: /* +(axmin)..sup * 0..0 */
	  goto ret;
	case 0x30: /* inf..sup * inf..-(aymax) */
	case 0x31: /* inf..sup * inf..0 */
	case 0x32: /* inf..sup * inf..+(aymax) */
	case 0x33: /* inf..sup * inf..sup */
	case 0x37: /* inf..sup * -(aymin)..sup */
	case 0x3b: /* inf..sup * 0..sup */
	case 0x3f: /* inf..sup * +(aymin)..sup */
	default:
	  continue;
	case 0x90: /* 0..0 * inf..-(aymax) */
	case 0x94: /* 0..0 * -(aymin)..-(aymax) */
	case 0x91: /* 0..0 * inf..0 */
	case 0x95: /* 0..0 * -(aymin)..0 */
	case 0x92: /* 0..0 * inf..+(aymax) */
	case 0x93: /* 0..0 * inf..sup */
	case 0x96: /* 0..0 * -(aymin)..+(aymax) */
	case 0x97: /* 0..0 * -(aymin)..sup */
	case 0x9a: /* 0..0 * 0..+(aymax) */
	case 0x9b: /* 0..0 * 0..sup */
	case 0x9e: /* 0..0 * +(aymin)..+(aymax) */
	case 0x9f: /* 0..0 * +(aymin)..sup */
	  newmin = TaggedZero;
	  newmax = newmin;
	  break;
	case 0xa0: /* 0..+(axmax) * inf..-(aymax) */
	case 0xa1: /* 0..+(axmax) * inf..0 */
	case 0xa2: /* 0..+(axmax) * inf..+(aymax) */
	case 0xa3: /* 0..+(axmax) * inf..sup */
	case 0xa7: /* 0..+(axmax) * -(aymin)..sup */
	case 0xab: /* 0..+(axmax) * 0..sup */
	case 0xaf: /* 0..+(axmax) * +(aymin)..sup */
	case 0xe1: /* +(axmin)..+(axmax) * inf..0 */
	case 0xe2: /* +(axmin)..+(axmax) * inf..+(aymax) */
	case 0xe3: /* +(axmin)..+(axmax) * inf..sup */
	case 0xe7: /* +(axmin)..+(axmax) * -(aymin)..sup */
	case 0xeb: /* +(axmin)..+(axmax) * 0..sup */
	  newmin = TaggedZero;
	  newmax = axmax;
	  break;
	case 0xb0: /* 0..sup * inf..-(aymax) */
	case 0xb1: /* 0..sup * inf..0 */
	case 0xb2: /* 0..sup * inf..+(aymax) */
	case 0xb3: /* 0..sup * inf..sup */
	case 0xb7: /* 0..sup * -(aymin)..sup */
	case 0xbb: /* 0..sup * 0..sup */
	case 0xbf: /* 0..sup * +(aymin)..sup */
	case 0xf0: /* +(axmin)..sup * inf..-(aymax) */
	case 0xf1: /* +(axmin)..sup * inf..0 */
	case 0xf2: /* +(axmin)..sup * inf..+(aymax) */
	case 0xf3: /* +(axmin)..sup * inf..sup */
	case 0xf7: /* +(axmin)..sup * -(aymin)..sup */
	case 0xfb: /* +(axmin)..sup * 0..sup */
	case 0xff: /* +(axmin)..sup * +(aymin)..sup */
	  newmin = TaggedZero;
	  newmax = Sup;
	  break;
	case 0xba: /* 0..sup * 0..+(aymax) */
	case 0xbe: /* 0..sup * +(aymin)..+(aymax) */
	case 0xfa: /* +(axmin)..sup * 0..+(aymax) */
	case 0xfe: /* +(axmin)..sup * +(aymin)..+(aymax) */
	  newmin = TaggedZero;
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  break;
	case 0xb4: /* 0..sup * -(aymin)..-(aymax) */
	case 0xb5: /* 0..sup * -(aymin)..0 */
	case 0xf4: /* +(axmin)..sup * -(aymin)..-(aymax) */
	case 0xf5: /* +(axmin)..sup * -(aymin)..0 */
	  newmin = TaggedZero;
	  newmax = fd_safe_minus(aymin,MakeSmall(1));
	  break;
	case 0xb6: /* 0..sup * -(aymin)..+(aymax) */
	case 0xf6: /* +(axmin)..sup * -(aymin)..+(aymax) */
	  newmin = TaggedZero;
	  newmax = fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1));
	  break;
	case 0xaa: /* 0..+(axmax) * 0..+(aymax) */
	case 0xae: /* 0..+(axmax) * +(aymin)..+(aymax) */
	case 0xea: /* +(axmin)..+(axmax) * 0..+(aymax) */
	  newmin = TaggedZero;
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  break;
	case 0xa4: /* 0..+(axmax) * -(aymin)..-(aymax) */
	case 0xa5: /* 0..+(axmax) * -(aymin)..0 */
	case 0xe5: /* +(axmin)..+(axmax) * -(aymin)..0 */
	  newmin = TaggedZero;
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymin,MakeSmall(1)));
	  break;
	case 0xa6: /* 0..+(axmax) * -(aymin)..+(aymax) */
	case 0xe6: /* +(axmin)..+(axmax) * -(aymin)..+(aymax) */
	  newmin = TaggedZero;
	  newmax = fd_safe_min(axmax,fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1)));
	  break;
	case 0xa: /* inf..-(axmax) * 0..+(aymax) */
	case 0xe: /* inf..-(axmax) * +(aymin)..+(aymax) */
	case 0x1a: /* inf..0 * 0..+(aymax) */
	case 0x1e: /* inf..0 * +(aymin)..+(aymax) */
	  newmin = fd_safe_minus(MakeSmall(1),aymax);
	  newmax = TaggedZero;
	  break;
	case 0x3a: /* inf..sup * 0..+(aymax) */
	case 0x3e: /* inf..sup * +(aymin)..+(aymax) */
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  newmin = fd_safe_negate(newmax);
	  break;
	case 0x2a: /* inf..+(axmax) * 0..+(aymax) */
	case 0x2e: /* inf..+(axmax) * +(aymin)..+(aymax) */
	  newmin = fd_safe_minus(MakeSmall(1),aymax);
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  break;
	case 0x4: /* inf..-(axmax) * -(aymin)..-(aymax) */
	case 0x5: /* inf..-(axmax) * -(aymin)..0 */
	case 0x14: /* inf..0 * -(aymin)..-(aymax) */
	case 0x15: /* inf..0 * -(aymin)..0 */
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = TaggedZero;
	  break;
	case 0x34: /* inf..sup * -(aymin)..-(aymax) */
	case 0x35: /* inf..sup * -(aymin)..0 */
	  newmax = fd_safe_minus(aymin,MakeSmall(1));
	  newmin = fd_safe_negate(newmax);
	  break;
	case 0x24: /* inf..+(axmax) * -(aymin)..-(aymax) */
	case 0x25: /* inf..+(axmax) * -(aymin)..0 */
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymin,MakeSmall(1)));
	  break;
	case 0x6: /* inf..-(axmax) * -(aymin)..+(aymax) */
	case 0x16: /* inf..0 * -(aymin)..+(aymax) */
	  newmin = fd_safe_minus(MakeSmall(1),fd_safe_max(aymin,aymax));
	  newmax = TaggedZero;
	  break;
	case 0x36: /* inf..sup * -(aymin)..+(aymax) */
	  newmax = fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1));
	  newmin = fd_safe_negate(newmax);
	  break;
	case 0x26: /* inf..+(axmax) * -(aymin)..+(aymax) */
	  newmin = fd_safe_minus(MakeSmall(1),fd_safe_max(aymin,aymax));
	  newmax = fd_safe_min(axmax,fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1)));
	  break;
	case 0x41: /* -(axmin)..-(axmax) * inf..0 */
	case 0x42: /* -(axmin)..-(axmax) * inf..+(aymax) */
	case 0x43: /* -(axmin)..-(axmax) * inf..sup */
	case 0x47: /* -(axmin)..-(axmax) * -(aymin)..sup */
	case 0x4b: /* -(axmin)..-(axmax) * 0..sup */
	case 0x50: /* -(axmin)..0 * inf..-(aymax) */
	case 0x51: /* -(axmin)..0 * inf..0 */
	case 0x52: /* -(axmin)..0 * inf..+(aymax) */
	case 0x53: /* -(axmin)..0 * inf..sup */
	case 0x57: /* -(axmin)..0 * -(aymin)..sup */
	case 0x5b: /* -(axmin)..0 * 0..sup */
	case 0x5f: /* -(axmin)..0 * +(aymin)..sup */
	  newmin = fd_safe_negate(axmin);
	  newmax = TaggedZero;
	  break;
	case 0x60: /* -(axmin)..+(axmax) * inf..-(aymax) */
	case 0x61: /* -(axmin)..+(axmax) * inf..0 */
	case 0x62: /* -(axmin)..+(axmax) * inf..+(aymax) */
	case 0x63: /* -(axmin)..+(axmax) * inf..sup */
	case 0x67: /* -(axmin)..+(axmax) * -(aymin)..sup */
	case 0x6b: /* -(axmin)..+(axmax) * 0..sup */
	case 0x6f: /* -(axmin)..+(axmax) * +(aymin)..sup */
	  newmin = fd_safe_negate(axmin);
	  newmax = axmax;
	  break;
	case 0x70: /* -(axmin)..sup * inf..-(aymax) */
	case 0x71: /* -(axmin)..sup * inf..0 */
	case 0x72: /* -(axmin)..sup * inf..+(aymax) */
	case 0x73: /* -(axmin)..sup * inf..sup */
	case 0x77: /* -(axmin)..sup * -(aymin)..sup */
	case 0x7b: /* -(axmin)..sup * 0..sup */
	case 0x7f: /* -(axmin)..sup * +(aymin)..sup */
	  newmin = fd_safe_negate(axmin);
	  newmax = Sup;
	  break;
	case 0x0: /* inf..-(axmax) * inf..-(aymax) */
	case 0x1: /* inf..-(axmax) * inf..0 */
	case 0x2: /* inf..-(axmax) * inf..+(aymax) */
	case 0x3: /* inf..-(axmax) * inf..sup */
	case 0x7: /* inf..-(axmax) * -(aymin)..sup */
	case 0xb: /* inf..-(axmax) * 0..sup */
	case 0xf: /* inf..-(axmax) * +(aymin)..sup */
	case 0x10: /* inf..0 * inf..-(aymax) */
	case 0x11: /* inf..0 * inf..0 */
	case 0x12: /* inf..0 * inf..+(aymax) */
	case 0x13: /* inf..0 * inf..sup */
	case 0x17: /* inf..0 * -(aymin)..sup */
	case 0x1b: /* inf..0 * 0..sup */
	case 0x1f: /* inf..0 * +(aymin)..sup */
	  newmin = Inf;
	  newmax = TaggedZero;
	  break;
	case 0x20: /* inf..+(axmax) * inf..-(aymax) */
	case 0x21: /* inf..+(axmax) * inf..0 */
	case 0x22: /* inf..+(axmax) * inf..+(aymax) */
	case 0x23: /* inf..+(axmax) * inf..sup */
	case 0x27: /* inf..+(axmax) * -(aymin)..sup */
	case 0x2b: /* inf..+(axmax) * 0..sup */
	case 0x2f: /* inf..+(axmax) * +(aymin)..sup */
	  newmin = Inf;
	  newmax = axmax;
	  break;
	case 0x4a: /* -(axmin)..-(axmax) * 0..+(aymax) */
	case 0x5a: /* -(axmin)..0 * 0..+(aymax) */
	case 0x5e: /* -(axmin)..0 * +(aymin)..+(aymax) */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymax,MakeSmall(1))));
	  newmax = TaggedZero;
	  break;
	case 0x7a: /* -(axmin)..sup * 0..+(aymax) */
	case 0x7e: /* -(axmin)..sup * +(aymin)..+(aymax) */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymax,MakeSmall(1))));
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  break;
	case 0x6a: /* -(axmin)..+(axmax) * 0..+(aymax) */
	case 0x6e: /* -(axmin)..+(axmax) * +(aymin)..+(aymax) */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymax,MakeSmall(1))));
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  break;
	case 0x45: /* -(axmin)..-(axmax) * -(aymin)..0 */
	case 0x54: /* -(axmin)..0 * -(aymin)..-(aymax) */
	case 0x55: /* -(axmin)..0 * -(aymin)..0 */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	  newmax = TaggedZero;
	  break;
	case 0x74: /* -(axmin)..sup * -(aymin)..-(aymax) */
	case 0x75: /* -(axmin)..sup * -(aymin)..0 */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	  newmax = fd_safe_minus(aymin,MakeSmall(1));
	  break;
	case 0x64: /* -(axmin)..+(axmax) * -(aymin)..-(aymax) */
	case 0x65: /* -(axmin)..+(axmax) * -(aymin)..0 */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	  newmax = fd_safe_min(axmax,fd_safe_minus(aymin,MakeSmall(1)));
	  break;
	case 0x46: /* -(axmin)..-(axmax) * -(aymin)..+(aymax) */
	case 0x56: /* -(axmin)..0 * -(aymin)..+(aymax) */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1))));
	  newmax = TaggedZero;
	  break;
	case 0x76: /* -(axmin)..sup * -(aymin)..+(aymax) */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1))));
	  newmax = fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1));
	  break;
	case 0x66: /* -(axmin)..+(axmax) * -(aymin)..+(aymax) */
	  newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1))));
	  newmax = fd_safe_min(axmax,fd_safe_minus(fd_safe_max(aymin,aymax),MakeSmall(1)));
	  break;
	case 0xe0: /* +(axmin)..+(axmax) * inf..-(aymax) */
	  if (Tlt(axmax,aymax)) {
	    newmin = axmin;
	    newmax = axmax;
	  } else {
	    newmin = TaggedZero;
	    newmax = axmax;
	  }
	  break;
	case 0xe4: /* +(axmin)..+(axmax) * -(aymin)..-(aymax) */
	  if (Tlt(axmax,aymax)) {
	    newmin = axmin;
	    newmax = axmax;
	  } else {
	    newmin = TaggedZero;
	    newmax = fd_safe_min(axmax,fd_safe_minus(aymin,MakeSmall(1)));
	  }
	  break;
	case 0xef: /* +(axmin)..+(axmax) * +(aymin)..sup */
	  if (Tlt(axmax,aymin)) {
	    newmin = axmin;
	    newmax = axmax;
	  } else {
	    newmin = TaggedZero;
	    newmax = axmax;
	  }
	  break;
	case 0xee: /* +(axmin)..+(axmax) * +(aymin)..+(aymax) */
	  if (Tlt(axmax,aymin)) {
	    newmin = axmin;
	    newmax = axmax;
	  } else {
	    newmin = TaggedZero;
	    newmax = fd_safe_min(axmax,fd_safe_minus(aymax,MakeSmall(1)));
	  }
	  break;
	case 0x40: /* -(axmin)..-(axmax) * inf..-(aymax) */
	  if (Tlt(axmin,aymax)) {
	    newmin = fd_safe_negate(axmin);
	    newmax = fd_safe_negate(axmax);
	  } else {
	    newmin = fd_safe_negate(axmin);
	    newmax = TaggedZero;
	  }
	  break;
	case 0x44: /* -(axmin)..-(axmax) * -(aymin)..-(aymax) */
	  if (Tlt(axmin,aymax)) {
	    newmin = fd_safe_negate(axmin);
	    newmax = fd_safe_negate(axmax);
	  } else {
	    newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymin,MakeSmall(1))));
	    newmax = TaggedZero;
	  }
	  break;
	case 0x4f: /* -(axmin)..-(axmax) * +(aymin)..sup */
	  if (Tlt(axmin,aymin)) {
	    newmin = fd_safe_negate(axmin);
	    newmax = fd_safe_negate(axmax);
	  } else {
	    newmin = fd_safe_negate(axmin);
	    newmax = TaggedZero;
	  }
	  break;
	case 0x4e: /* -(axmin)..-(axmax) * +(aymin)..+(aymax) */
	  if (Tlt(axmin,aymin)) {
	    newmin = fd_safe_negate(axmin);
	    newmax = fd_safe_negate(axmax);
	  } else {
	    newmin = fd_safe_negate(fd_safe_min(axmin,fd_safe_minus(aymax,MakeSmall(1))));
	    newmax = TaggedZero;
	  }
	  break;
	}
	if (dvar_fix_interval_t(dvz, newmin, newmax)<0) {
	  if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	    fd.fd_overflow = TRUE;
	  goto ret;
	}
	break;
      case 1:			/* (X,Z) => Y */
	axmin = (Tgez(xmin) ? xmin : fd_safe_negate_val(xmin));
	axmax = (Tgez(xmax) ? xmax : fd_safe_negate_val(xmax));
	azmin = (Tgez(zmin) ? zmin : fd_safe_negate_val(zmin));
	azmax = (Tgez(zmax) ? zmax : fd_safe_negate_val(zmax));
	switch (ARITH_DISPATCH(xmin,xmax,zmin,zmax)) {
	  /* AUTOMATICALLY GENERATED CASES FOR rem PRUNING DVAR dvy */
	case 0xe: /* inf..-(axmax) * +(azmin)..+(azmax) */
	case 0xf: /* inf..-(axmax) * +(azmin)..sup */
	case 0x4e: /* -(axmin)..-(axmax) * +(azmin)..+(azmax) */
	case 0x4f: /* -(axmin)..-(axmax) * +(azmin)..sup */
	case 0x1e: /* inf..0 * +(azmin)..+(azmax) */
	case 0x1f: /* inf..0 * +(azmin)..sup */
	case 0x5e: /* -(axmin)..0 * +(azmin)..+(azmax) */
	case 0x5f: /* -(axmin)..0 * +(azmin)..sup */
	case 0x90: /* 0..0 * inf..-(azmax) */
	case 0x94: /* 0..0 * -(azmin)..-(azmax) */
	case 0x9e: /* 0..0 * +(azmin)..+(azmax) */
	case 0x9f: /* 0..0 * +(azmin)..sup */
	case 0xa0: /* 0..+(axmax) * inf..-(azmax) */
	case 0xa4: /* 0..+(axmax) * -(azmin)..-(azmax) */
	case 0xb0: /* 0..sup * inf..-(azmax) */
	case 0xb4: /* 0..sup * -(azmin)..-(azmax) */
	case 0xe0: /* +(axmin)..+(axmax) * inf..-(azmax) */
	case 0xe4: /* +(axmin)..+(axmax) * -(azmin)..-(azmax) */
	case 0xf0: /* +(axmin)..sup * inf..-(azmax) */
	case 0xf4: /* +(axmin)..sup * -(azmin)..-(azmax) */
	  goto ret;
	case 0x2: /* inf..-(axmax) * inf..+(azmax) */
	case 0x3: /* inf..-(axmax) * inf..sup */
	case 0x6: /* inf..-(axmax) * -(azmin)..+(azmax) */
	case 0x7: /* inf..-(axmax) * -(azmin)..sup */
	case 0x42: /* -(axmin)..-(axmax) * inf..+(azmax) */
	case 0x43: /* -(axmin)..-(axmax) * inf..sup */
	case 0x1: /* inf..-(axmax) * inf..0 */
	case 0x5: /* inf..-(axmax) * -(azmin)..0 */
	case 0x41: /* -(axmin)..-(axmax) * inf..0 */
	case 0x9: /* inf..-(axmax) * 0..0 */
	case 0xa: /* inf..-(axmax) * 0..+(azmax) */
	case 0xb: /* inf..-(axmax) * 0..sup */
	case 0x12: /* inf..0 * inf..+(azmax) */
	case 0x13: /* inf..0 * inf..sup */
	case 0x16: /* inf..0 * -(azmin)..+(azmax) */
	case 0x17: /* inf..0 * -(azmin)..sup */
	case 0x52: /* -(axmin)..0 * inf..+(azmax) */
	case 0x53: /* -(axmin)..0 * inf..sup */
	case 0x56: /* -(axmin)..0 * -(azmin)..+(azmax) */
	case 0x57: /* -(axmin)..0 * -(azmin)..sup */
	case 0x11: /* inf..0 * inf..0 */
	case 0x15: /* inf..0 * -(azmin)..0 */
	case 0x51: /* -(axmin)..0 * inf..0 */
	case 0x55: /* -(axmin)..0 * -(azmin)..0 */
	case 0x19: /* inf..0 * 0..0 */
	case 0x59: /* -(axmin)..0 * 0..0 */
	case 0x1a: /* inf..0 * 0..+(azmax) */
	case 0x1b: /* inf..0 * 0..sup */
	case 0x5a: /* -(axmin)..0 * 0..+(azmax) */
	case 0x5b: /* -(axmin)..0 * 0..sup */
	case 0x22: /* inf..+(axmax) * inf..+(azmax) */
	case 0x23: /* inf..+(axmax) * inf..sup */
	case 0x26: /* inf..+(axmax) * -(azmin)..+(azmax) */
	case 0x27: /* inf..+(axmax) * -(azmin)..sup */
	case 0x32: /* inf..sup * inf..+(azmax) */
	case 0x33: /* inf..sup * inf..sup */
	case 0x36: /* inf..sup * -(azmin)..+(azmax) */
	case 0x37: /* inf..sup * -(azmin)..sup */
	case 0x62: /* -(axmin)..+(axmax) * inf..+(azmax) */
	case 0x63: /* -(axmin)..+(axmax) * inf..sup */
	case 0x66: /* -(axmin)..+(axmax) * -(azmin)..+(azmax) */
	case 0x67: /* -(axmin)..+(axmax) * -(azmin)..sup */
	case 0x72: /* -(axmin)..sup * inf..+(azmax) */
	case 0x73: /* -(axmin)..sup * inf..sup */
	case 0x76: /* -(axmin)..sup * -(azmin)..+(azmax) */
	case 0x77: /* -(axmin)..sup * -(azmin)..sup */
	case 0x21: /* inf..+(axmax) * inf..0 */
	case 0x25: /* inf..+(axmax) * -(azmin)..0 */
	case 0x31: /* inf..sup * inf..0 */
	case 0x35: /* inf..sup * -(azmin)..0 */
	case 0x61: /* -(axmin)..+(axmax) * inf..0 */
	case 0x65: /* -(axmin)..+(axmax) * -(azmin)..0 */
	case 0x71: /* -(axmin)..sup * inf..0 */
	case 0x75: /* -(axmin)..sup * -(azmin)..0 */
	case 0x29: /* inf..+(axmax) * 0..0 */
	case 0x39: /* inf..sup * 0..0 */
	case 0x69: /* -(axmin)..+(axmax) * 0..0 */
	case 0x79: /* -(axmin)..sup * 0..0 */
	case 0x2a: /* inf..+(axmax) * 0..+(azmax) */
	case 0x2b: /* inf..+(axmax) * 0..sup */
	case 0x3a: /* inf..sup * 0..+(azmax) */
	case 0x3b: /* inf..sup * 0..sup */
	case 0x6a: /* -(axmin)..+(axmax) * 0..+(azmax) */
	case 0x6b: /* -(axmin)..+(axmax) * 0..sup */
	case 0x7a: /* -(axmin)..sup * 0..+(azmax) */
	case 0x7b: /* -(axmin)..sup * 0..sup */
	case 0x92: /* 0..0 * inf..+(azmax) */
	case 0x93: /* 0..0 * inf..sup */
	case 0x96: /* 0..0 * -(azmin)..+(azmax) */
	case 0x97: /* 0..0 * -(azmin)..sup */
	case 0x91: /* 0..0 * inf..0 */
	case 0x95: /* 0..0 * -(azmin)..0 */
	case 0x99: /* 0..0 * 0..0 */
	case 0x9a: /* 0..0 * 0..+(azmax) */
	case 0x9b: /* 0..0 * 0..sup */
	case 0xa2: /* 0..+(axmax) * inf..+(azmax) */
	case 0xa3: /* 0..+(axmax) * inf..sup */
	case 0xa6: /* 0..+(axmax) * -(azmin)..+(azmax) */
	case 0xa7: /* 0..+(axmax) * -(azmin)..sup */
	case 0xb2: /* 0..sup * inf..+(azmax) */
	case 0xb3: /* 0..sup * inf..sup */
	case 0xb6: /* 0..sup * -(azmin)..+(azmax) */
	case 0xb7: /* 0..sup * -(azmin)..sup */
	case 0xa1: /* 0..+(axmax) * inf..0 */
	case 0xa5: /* 0..+(axmax) * -(azmin)..0 */
	case 0xb1: /* 0..sup * inf..0 */
	case 0xb5: /* 0..sup * -(azmin)..0 */
	case 0xa9: /* 0..+(axmax) * 0..0 */
	case 0xb9: /* 0..sup * 0..0 */
	case 0xaa: /* 0..+(axmax) * 0..+(azmax) */
	case 0xab: /* 0..+(axmax) * 0..sup */
	case 0xba: /* 0..sup * 0..+(azmax) */
	case 0xbb: /* 0..sup * 0..sup */
	case 0xe3: /* +(axmin)..+(axmax) * inf..sup */
	case 0xe7: /* +(axmin)..+(axmax) * -(azmin)..sup */
	case 0xf2: /* +(axmin)..sup * inf..+(azmax) */
	case 0xf3: /* +(axmin)..sup * inf..sup */
	case 0xf6: /* +(axmin)..sup * -(azmin)..+(azmax) */
	case 0xf7: /* +(axmin)..sup * -(azmin)..sup */
	case 0xf1: /* +(axmin)..sup * inf..0 */
	case 0xf5: /* +(axmin)..sup * -(azmin)..0 */
	case 0xf9: /* +(axmin)..sup * 0..0 */
	case 0xeb: /* +(axmin)..+(axmax) * 0..sup */
	case 0xfa: /* +(axmin)..sup * 0..+(azmax) */
	case 0xfb: /* +(axmin)..sup * 0..sup */
	default:
	  continue;
	case 0xe1: /* +(axmin)..+(axmax) * inf..0 */
	case 0xe5: /* +(axmin)..+(axmax) * -(azmin)..0 */
	case 0xe9: /* +(axmin)..+(axmax) * 0..0 */
	  newmin = fd_safe_negate(axmax);
	  newmax = axmax;
	  break;
	case 0x49: /* -(axmin)..-(axmax) * 0..0 */
	case 0x4a: /* -(axmin)..-(axmax) * 0..+(azmax) */
	case 0x4b: /* -(axmin)..-(axmax) * 0..sup */
	  newmin = fd_safe_negate(axmin);
	  newmax = axmin;
	  break;
	case 0x46: /* -(axmin)..-(axmax) * -(azmin)..+(azmax) */
	case 0x47: /* -(axmin)..-(axmax) * -(azmin)..sup */
	case 0x45: /* -(axmin)..-(axmax) * -(azmin)..0 */
	  if (Tle(axmax,azmin)) {
	    continue;
	  } else {
	    newmin = fd_safe_negate(axmin);
	    newmax = axmin;
	  }
	  break;
	case 0xe2: /* +(axmin)..+(axmax) * inf..+(azmax) */
	case 0xe6: /* +(axmin)..+(axmax) * -(azmin)..+(azmax) */
	case 0xea: /* +(axmin)..+(axmax) * 0..+(azmax) */
	  if (Tle(axmin,azmax)) {
	    continue;
	  } else {
	    newmin = fd_safe_negate(axmax);
	    newmax = axmax;
	  }
	  break;
	case 0x0: /* inf..-(axmax) * inf..-(azmax) */
	case 0x4: /* inf..-(axmax) * -(azmin)..-(azmax) */
	case 0x10: /* inf..0 * inf..-(azmax) */
	case 0x14: /* inf..0 * -(azmin)..-(azmax) */
	case 0x20: /* inf..+(axmax) * inf..-(azmax) */
	case 0x24: /* inf..+(axmax) * -(azmin)..-(azmax) */
	case 0x30: /* inf..sup * inf..-(azmax) */
	case 0x34: /* inf..sup * -(azmin)..-(azmax) */
	  newmin = fd_safe_negate(azmax);
	  newmax = azmax;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0x3e: /* inf..sup * +(azmin)..+(azmax) */
	case 0x3f: /* inf..sup * +(azmin)..sup */
	case 0x7e: /* -(axmin)..sup * +(azmin)..+(azmax) */
	case 0x7f: /* -(axmin)..sup * +(azmin)..sup */
	case 0xbe: /* 0..sup * +(azmin)..+(azmax) */
	case 0xbf: /* 0..sup * +(azmin)..sup */
	case 0xfe: /* +(axmin)..sup * +(azmin)..+(azmax) */
	case 0xff: /* +(axmin)..sup * +(azmin)..sup */
	  newmin = fd_safe_negate(azmin);
	  newmax = azmin;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0x50: /* -(axmin)..0 * inf..-(azmax) */
	case 0x54: /* -(axmin)..0 * -(azmin)..-(azmax) */
	case 0x60: /* -(axmin)..+(axmax) * inf..-(azmax) */
	case 0x64: /* -(axmin)..+(axmax) * -(azmin)..-(azmax) */
	case 0x70: /* -(axmin)..sup * inf..-(azmax) */
	case 0x74: /* -(axmin)..sup * -(azmin)..-(azmax) */
	  newmin = fd_safe_negate(azmax);
	  newmax = azmax;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  if (Tle(azmax,axmin)) {
	    continue;
	  } else {
	    newmax = fd_safe_minus(axmin,azmax);
	    newmin = fd_safe_negate(newmax);
	  }
	  break;
	case 0x2e: /* inf..+(axmax) * +(azmin)..+(azmax) */
	case 0x2f: /* inf..+(axmax) * +(azmin)..sup */
	case 0x6e: /* -(axmin)..+(axmax) * +(azmin)..+(azmax) */
	case 0x6f: /* -(axmin)..+(axmax) * +(azmin)..sup */
	case 0xae: /* 0..+(axmax) * +(azmin)..+(azmax) */
	case 0xaf: /* 0..+(axmax) * +(azmin)..sup */
	  newmin = fd_safe_negate(azmin);
	  newmax = azmin;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  if (Tle(azmin,axmax)) {
	    continue;
	  } else {
	    newmax = fd_safe_minus(axmax,azmin);
	    newmin = fd_safe_negate(newmax);
	  }
	  break;
	case 0x40: /* -(axmin)..-(axmax) * inf..-(azmax) */
	  newmin = fd_safe_negate(azmax);
	  newmax = azmax;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  if (Tle(fd_safe_max(axmax,azmax),axmin)) {
	    continue;
	  } else {
	    newmax = fd_safe_minus(axmin,azmax);
	    newmin = fd_safe_negate(newmax);
	  }
	  break;
	case 0x44: /* -(axmin)..-(axmax) * -(azmin)..-(azmax) */
	  newmin = fd_safe_negate(azmax);
	  newmax = azmax;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  if (Tle(fd_safe_max(axmax,azmax),fd_safe_min(axmin,azmin))) {
	    continue;
	  } else {
	    newmax = fd_safe_minus(axmin,azmax);
	    newmin = fd_safe_negate(newmax);
	  }
	  break;
	case 0xef: /* +(axmin)..+(axmax) * +(azmin)..sup */
	  newmin = fd_safe_negate(azmin);
	  newmax = azmin;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  if (Tle(fd_safe_max(axmin,azmin),axmax)) {
	    continue;
	  } else {
	    newmax = fd_safe_minus(axmax,azmin);
	    newmin = fd_safe_negate(newmax);
	  }
	  break;
	case 0xee: /* +(axmin)..+(axmax) * +(azmin)..+(azmax) */
	  newmin = fd_safe_negate(azmin);
	  newmax = azmin;
	  if (dvar_prune_interval_t(dvy, newmin, newmax,w)<0)
	    goto ret;
	  if (Tle(fd_safe_max(axmin,azmin),fd_safe_min(axmax,azmax))) {
	    continue;
	  } else {
	    newmax = fd_safe_minus(axmax,azmin);
	    newmin = fd_safe_negate(newmax);
	  }
	  break;
	}
	if (dvar_fix_interval_t(dvy, newmin, newmax)<0) {
	  if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	    fd.fd_overflow = TRUE;
	  goto ret;
	}
	break;
      case 2:			/* (Y,Z) => X */
	aymin = (Tgez(ymin) ? ymin : fd_safe_negate_val(ymin));
	aymax = (Tgez(ymax) ? ymax : fd_safe_negate_val(ymax));
	azmin = (Tgez(zmin) ? zmin : fd_safe_negate_val(zmin));
	azmax = (Tgez(zmax) ? zmax : fd_safe_negate_val(zmax));
	switch (ARITH_DISPATCH(ymin,ymax,zmin,zmax)) {
	  /* AUTOMATICALLY GENERATED CASES FOR rem PRUNING DVAR dvx */
	case 0x90: /* 0..0 * inf..-(azmax) */
	case 0x94: /* 0..0 * -(azmin)..-(azmax) */
	case 0x91: /* 0..0 * inf..0 */
	case 0x95: /* 0..0 * -(azmin)..0 */
	case 0x92: /* 0..0 * inf..+(azmax) */
	case 0x93: /* 0..0 * inf..sup */
	case 0x96: /* 0..0 * -(azmin)..+(azmax) */
	case 0x97: /* 0..0 * -(azmin)..sup */
	case 0x99: /* 0..0 * 0..0 */
	case 0x9a: /* 0..0 * 0..+(azmax) */
	case 0x9b: /* 0..0 * 0..sup */
	case 0x9e: /* 0..0 * +(azmin)..+(azmax) */
	case 0x9f: /* 0..0 * +(azmin)..sup */
	  goto ret;
	case 0x1: /* inf..-(aymax) * inf..0 */
	case 0x41: /* -(aymin)..-(aymax) * inf..0 */
	case 0x2: /* inf..-(aymax) * inf..+(azmax) */
	case 0x3: /* inf..-(aymax) * inf..sup */
	case 0x7: /* inf..-(aymax) * -(azmin)..sup */
	case 0x42: /* -(aymin)..-(aymax) * inf..+(azmax) */
	case 0x43: /* -(aymin)..-(aymax) * inf..sup */
	case 0x47: /* -(aymin)..-(aymax) * -(azmin)..sup */
	case 0xb: /* inf..-(aymax) * 0..sup */
	case 0x4b: /* -(aymin)..-(aymax) * 0..sup */
	case 0x11: /* inf..0 * inf..0 */
	case 0x15: /* inf..0 * -(azmin)..0 */
	case 0x51: /* -(aymin)..0 * inf..0 */
	case 0x55: /* -(aymin)..0 * -(azmin)..0 */
	case 0x12: /* inf..0 * inf..+(azmax) */
	case 0x13: /* inf..0 * inf..sup */
	case 0x16: /* inf..0 * -(azmin)..+(azmax) */
	case 0x17: /* inf..0 * -(azmin)..sup */
	case 0x52: /* -(aymin)..0 * inf..+(azmax) */
	case 0x53: /* -(aymin)..0 * inf..sup */
	case 0x56: /* -(aymin)..0 * -(azmin)..+(azmax) */
	case 0x57: /* -(aymin)..0 * -(azmin)..sup */
	case 0x19: /* inf..0 * 0..0 */
	case 0x59: /* -(aymin)..0 * 0..0 */
	case 0x1a: /* inf..0 * 0..+(azmax) */
	case 0x1b: /* inf..0 * 0..sup */
	case 0x5a: /* -(aymin)..0 * 0..+(azmax) */
	case 0x5b: /* -(aymin)..0 * 0..sup */
	case 0x21: /* inf..+(aymax) * inf..0 */
	case 0x25: /* inf..+(aymax) * -(azmin)..0 */
	case 0x31: /* inf..sup * inf..0 */
	case 0x35: /* inf..sup * -(azmin)..0 */
	case 0x61: /* -(aymin)..+(aymax) * inf..0 */
	case 0x65: /* -(aymin)..+(aymax) * -(azmin)..0 */
	case 0x71: /* -(aymin)..sup * inf..0 */
	case 0x75: /* -(aymin)..sup * -(azmin)..0 */
	case 0x22: /* inf..+(aymax) * inf..+(azmax) */
	case 0x23: /* inf..+(aymax) * inf..sup */
	case 0x26: /* inf..+(aymax) * -(azmin)..+(azmax) */
	case 0x27: /* inf..+(aymax) * -(azmin)..sup */
	case 0x32: /* inf..sup * inf..+(azmax) */
	case 0x33: /* inf..sup * inf..sup */
	case 0x36: /* inf..sup * -(azmin)..+(azmax) */
	case 0x37: /* inf..sup * -(azmin)..sup */
	case 0x62: /* -(aymin)..+(aymax) * inf..+(azmax) */
	case 0x63: /* -(aymin)..+(aymax) * inf..sup */
	case 0x66: /* -(aymin)..+(aymax) * -(azmin)..+(azmax) */
	case 0x67: /* -(aymin)..+(aymax) * -(azmin)..sup */
	case 0x72: /* -(aymin)..sup * inf..+(azmax) */
	case 0x73: /* -(aymin)..sup * inf..sup */
	case 0x76: /* -(aymin)..sup * -(azmin)..+(azmax) */
	case 0x77: /* -(aymin)..sup * -(azmin)..sup */
	case 0x29: /* inf..+(aymax) * 0..0 */
	case 0x39: /* inf..sup * 0..0 */
	case 0x69: /* -(aymin)..+(aymax) * 0..0 */
	case 0x79: /* -(aymin)..sup * 0..0 */
	case 0x2a: /* inf..+(aymax) * 0..+(azmax) */
	case 0x2b: /* inf..+(aymax) * 0..sup */
	case 0x3a: /* inf..sup * 0..+(azmax) */
	case 0x3b: /* inf..sup * 0..sup */
	case 0x6a: /* -(aymin)..+(aymax) * 0..+(azmax) */
	case 0x6b: /* -(aymin)..+(aymax) * 0..sup */
	case 0x7a: /* -(aymin)..sup * 0..+(azmax) */
	case 0x7b: /* -(aymin)..sup * 0..sup */
	case 0xa1: /* 0..+(aymax) * inf..0 */
	case 0xa5: /* 0..+(aymax) * -(azmin)..0 */
	case 0xb1: /* 0..sup * inf..0 */
	case 0xb5: /* 0..sup * -(azmin)..0 */
	case 0xa2: /* 0..+(aymax) * inf..+(azmax) */
	case 0xa3: /* 0..+(aymax) * inf..sup */
	case 0xa6: /* 0..+(aymax) * -(azmin)..+(azmax) */
	case 0xa7: /* 0..+(aymax) * -(azmin)..sup */
	case 0xb2: /* 0..sup * inf..+(azmax) */
	case 0xb3: /* 0..sup * inf..sup */
	case 0xb6: /* 0..sup * -(azmin)..+(azmax) */
	case 0xb7: /* 0..sup * -(azmin)..sup */
	case 0xa9: /* 0..+(aymax) * 0..0 */
	case 0xb9: /* 0..sup * 0..0 */
	case 0xaa: /* 0..+(aymax) * 0..+(azmax) */
	case 0xab: /* 0..+(aymax) * 0..sup */
	case 0xba: /* 0..sup * 0..+(azmax) */
	case 0xbb: /* 0..sup * 0..sup */
	case 0xe1: /* +(aymin)..+(aymax) * inf..0 */
	case 0xf1: /* +(aymin)..sup * inf..0 */
	case 0xe2: /* +(aymin)..+(aymax) * inf..+(azmax) */
	case 0xe3: /* +(aymin)..+(aymax) * inf..sup */
	case 0xe7: /* +(aymin)..+(aymax) * -(azmin)..sup */
	case 0xf2: /* +(aymin)..sup * inf..+(azmax) */
	case 0xf3: /* +(aymin)..sup * inf..sup */
	case 0xf7: /* +(aymin)..sup * -(azmin)..sup */
	case 0xeb: /* +(aymin)..+(aymax) * 0..sup */
	case 0xfb: /* +(aymin)..sup * 0..sup */
	default:
	  continue;
	case 0xf: /* inf..-(aymax) * +(azmin)..sup */
	case 0x4f: /* -(aymin)..-(aymax) * +(azmin)..sup */
	case 0x1e: /* inf..0 * +(azmin)..+(azmax) */
	case 0x1f: /* inf..0 * +(azmin)..sup */
	case 0x5e: /* -(aymin)..0 * +(azmin)..+(azmax) */
	case 0x5f: /* -(aymin)..0 * +(azmin)..sup */
	case 0x2e: /* inf..+(aymax) * +(azmin)..+(azmax) */
	case 0x2f: /* inf..+(aymax) * +(azmin)..sup */
	case 0x3e: /* inf..sup * +(azmin)..+(azmax) */
	case 0x3f: /* inf..sup * +(azmin)..sup */
	case 0x6e: /* -(aymin)..+(aymax) * +(azmin)..+(azmax) */
	case 0x6f: /* -(aymin)..+(aymax) * +(azmin)..sup */
	case 0x7e: /* -(aymin)..sup * +(azmin)..+(azmax) */
	case 0x7f: /* -(aymin)..sup * +(azmin)..sup */
	case 0xae: /* 0..+(aymax) * +(azmin)..+(azmax) */
	case 0xaf: /* 0..+(aymax) * +(azmin)..sup */
	case 0xbe: /* 0..sup * +(azmin)..+(azmax) */
	case 0xbf: /* 0..sup * +(azmin)..sup */
	case 0xef: /* +(aymin)..+(aymax) * +(azmin)..sup */
	case 0xff: /* +(aymin)..sup * +(azmin)..sup */
	  newmin = azmin;
	  newmax = Sup;
	  break;
	case 0x0: /* inf..-(aymax) * inf..-(azmax) */
	case 0x40: /* -(aymin)..-(aymax) * inf..-(azmax) */
	case 0x10: /* inf..0 * inf..-(azmax) */
	case 0x14: /* inf..0 * -(azmin)..-(azmax) */
	case 0x50: /* -(aymin)..0 * inf..-(azmax) */
	case 0x54: /* -(aymin)..0 * -(azmin)..-(azmax) */
	case 0x20: /* inf..+(aymax) * inf..-(azmax) */
	case 0x24: /* inf..+(aymax) * -(azmin)..-(azmax) */
	case 0x30: /* inf..sup * inf..-(azmax) */
	case 0x34: /* inf..sup * -(azmin)..-(azmax) */
	case 0x60: /* -(aymin)..+(aymax) * inf..-(azmax) */
	case 0x64: /* -(aymin)..+(aymax) * -(azmin)..-(azmax) */
	case 0x70: /* -(aymin)..sup * inf..-(azmax) */
	case 0x74: /* -(aymin)..sup * -(azmin)..-(azmax) */
	case 0xa0: /* 0..+(aymax) * inf..-(azmax) */
	case 0xa4: /* 0..+(aymax) * -(azmin)..-(azmax) */
	case 0xb0: /* 0..sup * inf..-(azmax) */
	case 0xb4: /* 0..sup * -(azmin)..-(azmax) */
	case 0xe0: /* +(aymin)..+(aymax) * inf..-(azmax) */
	case 0xf0: /* +(aymin)..sup * inf..-(azmax) */
	  newmin = Inf;
	  newmax = fd_safe_negate(azmax);
	  break;
	case 0xe: /* inf..-(aymax) * +(azmin)..+(azmax) */
	case 0x4e: /* -(aymin)..-(aymax) * +(azmin)..+(azmax) */
	  newmin = fd_safe_plus(azmax,MakeSmall(1));
	  newmax = fd_safe_minus(fd_safe_plus(aymax,azmin),MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = azmin;
	  newmax = Sup;
	  break;
	case 0xee: /* +(aymin)..+(aymax) * +(azmin)..+(azmax) */
	case 0xfe: /* +(aymin)..sup * +(azmin)..+(azmax) */
	  newmin = fd_safe_plus(azmax,MakeSmall(1));
	  newmax = fd_safe_minus(fd_safe_plus(aymin,azmin),MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = azmin;
	  newmax = Sup;
	  break;
	case 0x4: /* inf..-(aymax) * -(azmin)..-(azmax) */
	case 0x44: /* -(aymin)..-(aymax) * -(azmin)..-(azmax) */
	  newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(aymax,azmax));
	  newmax = fd_safe_negate(fd_safe_plus(azmin,MakeSmall(1)));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = Inf;
	  newmax = fd_safe_negate(azmax);
	  break;
	case 0xe4: /* +(aymin)..+(aymax) * -(azmin)..-(azmax) */
	case 0xf4: /* +(aymin)..sup * -(azmin)..-(azmax) */
	  newmin = fd_safe_minus(MakeSmall(1),fd_safe_plus(aymin,azmax));
	  newmax = fd_safe_negate(fd_safe_plus(azmin,MakeSmall(1)));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = Inf;
	  newmax = fd_safe_negate(azmax);
	  break;
	case 0x9: /* inf..-(aymax) * 0..0 */
	case 0x49: /* -(aymin)..-(aymax) * 0..0 */
	  newmin = MakeSmall(1);
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymax);
	  newmax = MakeSmall(-1);
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0xa: /* inf..-(aymax) * 0..+(azmax) */
	case 0x4a: /* -(aymin)..-(aymax) * 0..+(azmax) */
	  newmin = fd_safe_plus(azmax,MakeSmall(1));
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymax);
	  newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0x5: /* inf..-(aymax) * -(azmin)..0 */
	case 0x45: /* -(aymin)..-(aymax) * -(azmin)..0 */
	  newmin = fd_safe_plus(azmin,MakeSmall(1));
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymax);
	  newmax = fd_safe_negate(fd_safe_plus(azmin,MakeSmall(1)));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0x6: /* inf..-(aymax) * -(azmin)..+(azmax) */
	case 0x46: /* -(aymin)..-(aymax) * -(azmin)..+(azmax) */
	  newmin = fd_safe_max(fd_safe_plus(azmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1)));
	  newmax = fd_safe_minus(aymax,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymax);
	  newmax = fd_safe_negate(fd_safe_max(fd_safe_plus(azmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0xe9: /* +(aymin)..+(aymax) * 0..0 */
	case 0xf9: /* +(aymin)..sup * 0..0 */
	  newmin = MakeSmall(1);
	  newmax = fd_safe_minus(aymin,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = MakeSmall(-1);
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0xea: /* +(aymin)..+(aymax) * 0..+(azmax) */
	case 0xfa: /* +(aymin)..sup * 0..+(azmax) */
	  newmin = fd_safe_plus(azmax,MakeSmall(1));
	  newmax = fd_safe_minus(aymin,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = fd_safe_negate(fd_safe_plus(azmax,MakeSmall(1)));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0xe5: /* +(aymin)..+(aymax) * -(azmin)..0 */
	case 0xf5: /* +(aymin)..sup * -(azmin)..0 */
	  newmin = fd_safe_plus(azmin,MakeSmall(1));
	  newmax = fd_safe_minus(aymin,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = fd_safe_negate(fd_safe_plus(azmin,MakeSmall(1)));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	case 0xe6: /* +(aymin)..+(aymax) * -(azmin)..+(azmax) */
	case 0xf6: /* +(aymin)..sup * -(azmin)..+(azmax) */
	  newmin = fd_safe_max(fd_safe_plus(azmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1)));
	  newmax = fd_safe_minus(aymin,MakeSmall(1));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  newmin = fd_safe_minus(MakeSmall(1),aymin);
	  newmax = fd_safe_negate(fd_safe_max(fd_safe_plus(azmin,MakeSmall(1)),fd_safe_plus(azmax,MakeSmall(1))));
	  if (dvar_prune_interval_t(dvx, newmin, newmax,w)<0)
	    goto ret;
	  continue;
	}
	if (dvar_fix_interval_t(dvx, newmin, newmax)<0) {
	  if (newmin==Sup || newmax==Inf) /* can't represent bounds */
	    fd.fd_overflow = TRUE;
	  goto ret;
	}      break;
      }
    }
  }
#if 0
  /* shaving */
  if (!shave_bounds(w,dvx,2))
    goto ret;
#endif
  if (dvar_is_integer(dvx) && dvar_is_integer(dvy) && dvar_is_integer(dvz)) {
    ent = dvar_min_l(dvx)%dvar_min_l(dvy)==dvar_min_l(dvz) ? 1 : -1;
  } else {
    ent = 0;
  }
  for (i=0; i<3; i++)
    dvar_pruning_done(w,dvx+i);
  for (i=0; i<3; i++)
    dvar_export(w,dvx+i);
 ret:
  if (ent==1)
    Pfree;
  dvar_export_done(w,Actions, ent);
}
